http://knockoutjs.com/ documentation by Steve Sanderson
- Automatic UI Refresh MVVM pattern for javascript
- Automatic dependency tracking
- Uses jQuery templates
- Declarative bindings Integrated templating
- Upgrade JSON to observable by using Knockout.mapping
- DependentObservable => Computed
Overview
var myViewModel = { personName: ko.observable('Ken'), personAge:103 };
The name is <span data-bind="text: personName"></span>
ko.applyBindings(myViewModel);
ko.applyBindings(myViewModel, document.getElementById('someElementId'));
myViewModel.personName(); to get
myViewModel.personName('Patrycja'); to set
myViewModel.personName('Patrycja').personAge(50);
var subscription = myViewModel.personName.subscribe(function(newValue) { alert(newValue); });
subscription.dispose();
this.fullName = ko.computed(function() { return this.firstName() + " " + this.lastName(); }, this);
function AppViewModel() {
var self = this;
self.firstName = ko.observable('Bob');
self.lastName = ko.observable('Smith');
self.fullName = ko.computed(function() {
return self.firstName() + " " + self.lastName();
});
}
this.fullName = ko.computed({
read: function () {
return this.firstName() + " " + this.lastName();
},
write: function (value) {
var lastSpacePos = value.lastIndexOf(" ");
if (lastSpacePos > 0) { // Ignore values with no space character
this.firstName(value.substring(0, lastSpacePos)); // Update "firstName"
this.lastName(value.substring(lastSpacePos + 1)); // Update "lastName"
}
},
owner: this
});
ko.applyBindings(new MyViewModel());
read, write, owner, deferEvaluation, disposeWhen, disposeWhenNodeIsRemoved
ko.isComputed, ko.isObservable, ko.isWriteableObservable
var myObservableArray = ko.observableArray([{ name: "Bungle", type: "Bear" }]);
myObservableArray.push('Some value'); // Adds the value and notifies observers
alert('The length of the array is ' + myObservableArray().length);
alert('The first element is ' + myObservableArray()[0]);
myObservableArray.indexOf('Blah'); //zero-based and -1 if not found
myObservableArray.slice(...);
myObservableArray.push('Some new value'); //adds a new item to the end of array
myObservableArray.pop(); //removes the last value from the array and returns it
myObservableArray.unshift('Some new value'); //inserts a new item at the beginning of the array
myObservableArray.shift(); //removes the first value from the array and returns it
myObservableArray.reverse(); //reverses the order of the array
myObservableArray.sort(); //sorts the array contents.
myObservableArray.sort(function(left, right)
{ return left.lastName == right.lastName ? 0 :
(left.lastName < right.lastName ? -1 : 1) });
myObservableArray.splice(1, 3);
myObservableArray.remove(someItem);
myObservableArray.remove(function(item) { return item.age < 18 });
myObservableArray.removeAll(['Chad', 132, undefined]);
myObservableArray.removeAll();
visible, text, html, css, style, attr
<div data-bind="css: { profitWarning: currentProfit() < 0 }">...</div>
<div data-bind="style: { color: currentProfit() < 0 ? 'red' : 'black' }">...</div>
<a data-bind="attr: { href: url, title: details }">...</a>
foreach, if, ifnot, with
<div data-bind="if: displayMessage">...</div>
click, event, submit, enable, disable, value, hasfocus, checked, options, selectedOptions, uniqueName
<button data-bind="click: incrementClickCounter">Click me</button>
<div data-bind="event: { mouseover: enableDetails, mouseout: disableDetails }">...</div>
<input data-bind="hasfocus: isSelected" />
ko.bindingHandlers.yourBindingName = { ... };
<div data-bind="template: { name: 'person-template', data: buyer }"> </div>
<script type="text/html" id="person-template">
<h3 data-bind="text: name"></h3>
<p>Credits: <span data-bind="text: credits"></span></p>
</script>
.extend({ throttle: 500 }); //delayed binding
var viewModel = ko.mapping.fromJS(data);
ko.mapping.fromJS(data, viewModel);
var unmapped = ko.mapping.toJS(viewModel);
Example
var viewModel = {
firstName: ko.observable("Ken"),
lastName: ko.observable("Van Gilbergen"),
friends: ko.observableArray([new friend("Steve"), new friend("Annie")]),
addFriend: function() {
this.friends.push(new friend("Tim"));
},
save: function() {
$.ajax({
url: "@Url.Action("Save")",
type: "post",
data: ko.toJSON(this),
contentType: "application/json",
success: function (result) { alert(result.message) }
});
}
};
viewModel.fullName = ko.computed(
function() {
return this.firstName() + " " + this.lastName();
}, viewModel);
ko.applyBindings(viewModel);
<input data-bind="value: firstName" />
function friend(name)
{
return {
name: ko.observable(name),
isOnTwitter: ko.observable(false),
twitterName: ko.observable,
remove: function ()
{
viewModel.friends.remove(this);
}
};
}
<div data-bind="template: 'friendsTemplate'"> </div>
<script id="friendsTemplate" type="text/html">
<ul>
{{each(index, friend) friends}}
<ul><li>${ friend.name } - ${ new Date }</li></ul>
<label><input type="checkbox" data-bind="checked: isOnTwitter" /> Is on twitter</label>
<input data-bind="value: twitterName, visible: isOnTwitter" />
{{/each}}
</ul>
</script>
<button data-bind="click: addFriend, enabled: friends().length < 5">Add Friend</button>
<script id="friendsTemplate2" type="text/html">
<ul><ul><li>${ data.name } - ${ new Date }</li></ul>
<button data-bind="click: remove">Remove
</script>
public JsonResult Save(Person person)
{
...
return Json(new { message });
}
public class Person
{
public string FirstName { get; set;}
public ICollection Friends { get; set; } }