Knockout Talk, Complete Demo
HTML
<script src="http://cdnjs.cloudflare.com/ajax/libs/knockout/2.1.0/knockout-min.js"></script>
<script src="https://github.com/downloads/rniemeyer/knockout-sortable/knockout-sortable.js"></script>
<div id="wrap">
<h2 data-bind="text: title"></h2>
<div data-bind="with: selectedQuestion">
<input data-bind="value: title" />
<select data-bind="value: type">
<option value="text">Single-Line Text</option>
<option value="textarea">Multi-Line Text</option>
<option value="dropdown">Drop Down List</option>
<option value="checkboxes">Check Box List</option>
<option value="radios">Radio Button List</option>
</select>
<!-- ko if: isMultipleChoice -->
<ol data-bind="sortable: answers">
<li><input data-bind="value: title" /><button data-bind="click: $parent.delete">Delete</button></li>
</ol>
<button data-bind="click: add">Add Another</button>
<!-- /ko -->
<button data-bind="click: $root.save">Save</button>
</div>
<ol data-bind="sortable: questions">
<li>
<label data-bind="text: title, attr: { for: 'eq' + $index() }"></label>
<!-- ko if: isText -->
<input data-bind="attr: { id: 'eq' + $index() }" />
<!-- /ko -->
<!-- ko if: isTextarea -->
<textarea data-bind="attr: { id: 'eq' + $index() }"></textarea>
<!-- /ko -->
<!-- ko if: isDropdown -->
<select data-bind="attr: { id: 'eq' + $index() }, foreach: answers">
<option data-bind="text: title"></option>
</select>
<!-- /ko -->
<ul class="utility-bar">
<li><button data-bind="click: $root.edit">edit</button></li>
<li><button data-bind="click: $root.copy">copy</button></li> ...
CSS
.utility-bar {float:right;}
.utility-bar li {display:inline;}
.clear {clear:both;}
JavaScript
/*globals ko */
var data = {
formId: 1,
title: 'Contact Form',
questions: [{
title: 'Name',
type: 'text'},
{
title: 'Reason',
type: 'dropdown',
answers: ['Sales', 'Support']},
{
title: 'Message',
type: 'textarea'}]
},
AjaxPersistanceManager = { submit: function (form) { console.dir(form); } },
QuestionViewModel = function (question) {
var self = this,
answers = $.map(question.answers || [], function (a) { return { title: ko.observable(a) }; });
self.title = ko.observable(question.title);
self.type = ko.observable(question.type);
self.answers = ko.observableArray(answers);
self.isText = ko.computed("hej");
self.isTextarea = ko.computed(function () { return self.type() === 'textarea'; });
self.isDropdown = ko.computed(function () { return self.type() === 'dropdown'; });
self.isCheckBoxes = ko.computed(function () { return self.type() === 'checkboxes'; });
self.isRadios = ko.computed(function () { return self.type() === 'radios'; });
self.isMultipleChoice = ko.computed(function () { return self.isDropdown() || self.isCheckBoxes() || self.isRadios(); });
self.delete = function (answer) {
self.answers.remove(answer);
};
self.add = function () {
self.answers.push({ title: ko.observable('') });
};
self.debug = ko.computed(function () { return ko.toJSON(self); });
},
FormViewModel = function (form) {
var self = this,
questions = $.map(form.questions, function (q) { return new QuestionViewModel(q); });
self.formId = ko.observable(form.formId);
self.title = ko.observable(form.title);
self.questions = ko.observableArray(questions);
self.selectedQuestion = ko.observable(null);
self.edit = function...