Dynamic Forms with KO

My implementation of Dynamic Forms with KO

by bmccord

HTML

<script src="http://knockoutjs.com/downloads/knockout-3.0.0rc.js"></script>
<script src="https://dl.dropboxusercontent.com/u/3531910/knockout.mapping-latest.debug.js"></script>
<script src="https://dl.dropboxusercontent.com/u/3531910/prettyprint.js"></script>
<script src="https://dl.dropboxusercontent.com/u/3531910/knockout.validation.js"></script>
<script src="http://code.jquery.com/ui/1.9.0/jquery-ui.js"></script>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.9.0/themes/base/jquery-ui.css">
<link rel="stylesheet" href="http://getbootstrap.com/2.3.2/assets/css/bootstrap.css">
<link rel="stylesheet" href="http://getbootstrap.com/2.3.2/assets/css/bootstrap-responsive.css">
<div data-bind="foreach: Fields">
    <div class="control-group form-inline row" data-bind="validationElement: Value">
        <div class="controls">
            <label class="control-label help-inline span2" data-bind="text: FieldName"></label>
            <div data-bind="template: {name: 'short-text-template', if:FieldType()==='ShortText'}">
            </div>
            <div data-bind="template: {name: 'long-text-template', if:FieldType()==='LongText'}">
            </div>
            <div data-bind="template: {name: 'date-template', if:FieldType()==='Date'}">
            </div>
            <div data-bind="template: {name: 'short-text-template', if:FieldType()==='Numeric'}">
            </div>
            <div data-bind="template: {name: 'checkbox-template', if:FieldType()==='Boolean'}">
            </div>
            <div data-bind="template: {name: 'radio-template', if:FieldType()==='Radio'}">
            </div>
            <div data-bind="template: {name: 'dropdown-template', if:FieldType()==='DropDown'}">
            </div>
            <div data-bind="template: {name: 'list-template', if:FieldType()==='List'}">
            </div>
            <label data-bind="validationMessage: Value" class="help-inline"></label>
        </div>
    </div>
</div>

<script type="text/html"...

JavaScript

ko.bindingHandlers.datepicker = {
        init: function (element, valueAccessor, allBindingsAccessor) {
            //initialize datepicker with some optional options
            var options = allBindingsAccessor().datepickerOptions || {};
            $(element).datepicker(options);

            //handle the field changing
            ko.utils.registerEventHandler(element, "change", function () {
                var observable = valueAccessor();
                observable($(element).datepicker("getDate"));
            });

            //handle disposal (if KO removes by the template binding)
            ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
                $(element).datepicker("destroy");
            });

            //handle .Net DateTime
            var value = ko.utils.unwrapObservable(valueAccessor());
            var obs = valueAccessor();

            if (obs() !== null && !isNaN(obs().replace(/\/Date\((-?\d+)\)\//, '$1'))) {
                obs(new Date(parseInt(value.replace(/\/Date\((-?\d+)\)\//, '$1'), 10)));
                $(element).datepicker("setDate", obs());
            }
        },
        update: function (element, valueAccessor) {
            var value = ko.utils.unwrapObservable(valueAccessor()),
                current = $(element).datepicker("getDate");

            if (value - current !== 0) {
                $(element).datepicker("setDate", value);
            }
        }
    };

    ko.bindingHandlers.prettyPrint = {
        update: function (element, valueAccessor) {
            element.innerHTML = '';
            var ppTable = prettyPrint(ko.toJS(ko.utils.unwrapObservable(valueAccessor())));
            element.appendChild(ppTable);
        }
    };

    ko.validation.configure({
        registerExtenders: true,
        messagesOnModified: false,
        insertMessages: false,
        parseInputAttributes: true,
        messageTemplate: null,
        grouping: { observable:true, deep: true },
       ...