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 },
...