Knockout
JavaScript library that helps you to create rich, responsive display and editor user interfaces with a clean underlying data model.
- Pure JavaScript library - works with any server or client-side technology
- Can be added on top of your existing web application without requiring major architectural changes
- Compact - around 13kb after gzipping
- Works on any mainstream browser (IE 6+, Firefox 2+, Chrome, Safari, others)
Model View ViewModel (MVVM)
- A model: your application’s stored data.
- A view model: a pure-code representation of the data and operations on a UI.
- A view: a visible, interactive UI representing the state of the view model.
Model
Just declare any JavaScript object:
var workshop = {
id: 104,
title: 'Vehicle Design: Sci-Fi Ship',
author: 'Paul Christopher',
price: 39.99
};
View
You can then create a very simple view of this view model using a declarative binding:
<h2>
<!-- ko text: title --><!-- /ko -->
<small data-bind="text: '(by ' + author + ')'"></small>
</h2>
<p>Price: $<!-- ko text: price --><!-- /ko --></p>
ViewModel
To activate Knockout, add the following line to a JS code:
ko.applyBindings(workshop);
Result
<h2>
<!-- ko text: title -->Vehicle Design: Sci-Fi Ship<!-- /ko -->
<small data-bind="text: '(by ' + author + ')'">(by Paul Christopher)</small>
</h2>
<p>Price: $<!-- ko text: price -->39.99<!-- /ko --></p>
The data-bind
A binding consists of two items, the binding name and value, separated by a colon. Here is an example of a single, simple binding:
Today's message is: <span data-bind="text: message"></span>
An element can include multiple bindings, with each binding separated by a comma.
Cellphone: <input data-bind="value: cellphoneNumber, enable: hasCellphone">
Binding values
<!-- variable (usually a property of the current view model -->
<div data-bind="visible: shouldShowMessage">...</div>
<!-- comparison and conditional -->
The item is <span data-bind="text: price() > 50 ? 'expensive' : 'cheap'"></span>.
<!-- function call and comparison -->
<button data-bind="enable: parseAreaCode(cellphoneNumber()) != '555'">...</button>
<!-- function expression -->
<div data-bind="click: function (data) { myFunction('param1', data) }">...</div>
<!-- object literal (with unquoted and quoted property names) -->
<div data-bind="with: {emotion: 'happy', 'facial-expression': 'smile'}">...</div>
Bindings
- Controlling text and appearance
- Control flow
- Working with form fields
- Rendering templates
Controlling text and appearance
The "visible" binding
The visible binding causes the associated DOM element to become hidden or visible according to the value you pass to the binding.
<div data-bind="visible: shouldShowMessage">
You will see this message only when "shouldShowMessage" holds a true value.
</div>
Using functions and expressions to control element visibility.
<div data-bind="visible: items.length > 0">
You will see this message only when 'items' has at least one member.
</div>
The "text" binding
The text binding causes the associated DOM element to display the text value of your parameter.
Today's message is: <span data-bind="text: message"></span>
The "html" binding
The html binding causes the associated DOM element to display the HTML specified by your parameter.
var viewModel = {
details: "<em>For further details, view the report <a href='report.html'>here</a>.</em>"
};
ko.applyBindings(viewModel);
<div data-bind="html: details"></div>
The "css" binding
The css binding adds or removes one or more named CSS classes to the associated DOM element.
<div data-bind="css: { profitWarning: currentProfit() < 0 }">
Profit Information
</div>
The "style" binding
The style binding adds or removes one or more style values to the associated DOM element.
<div data-bind="style: { color: currentProfit() < 0 ? 'red' : 'black' }">
Profit Information
</div>
The "attr" binding
The attr binding provides a generic way to set the value of any attribute for the associated DOM element.
<a data-bind="attr: { href: url, title: details }">
Report
</a>
Control flow
The "foreach" binding
The foreach binding duplicates a section of markup for each entry in an array, and binds each copy of that markup to the corresponding array item. This is especially useful for rendering lists or tables.
<table>
<thead>
<tr>
<th>First name</th>
<th>Last name</th>
</tr>
</thead>
<tbody data-bind="foreach: people">
<tr>
<td data-bind="text: firstName"></td>
<td data-bind="text: lastName"></td>
</tr>
</tbody>
</table>
The "if" binding
The if binding causes a section of markup to appear in your document (and to have its data-bind attributes applied), only if a specified expression evaluates to true.
<div data-bind="if: displayMessage">Here is a message.</div>
The "ifnot" binding
ifnot is the same as a negated if
<div data-bind="ifnot: someProperty">...</div>
…is equivalent to the following:
<div data-bind="if: !someProperty()">...</div>
The "with" binding
The with binding creates a new binding context, so that descendant elements are bound in the context of a specified object.
<h1 data-bind="text: city"></h1>
<p data-bind="with: coords">
Latitude: <span data-bind="text: latitude"></span>,
Longitude: <span data-bind="text: longitude"></span>
</p>
Working with form fields
The "click" binding
The click binding adds an event handler so that your chosen JavaScript function will be invoked when the associated DOM element is clicked.
<button data-bind="click: incrementClickCounter">Click me</button>
The "event" binding
The event binding allows you to add an event handler for a specified event so that your chosen JavaScript function will be invoked when that event is triggered for the associated DOM element.
<div data-bind="event: { mouseover: enableDetails, mouseout: disableDetails }">
Mouse over me
</div>
<div data-bind="visible: detailsEnabled">
Details
</div>
The "submit" binding
The submit binding adds an event handler so that your chosen JavaScript function will be invoked when the associated DOM element is submitted.
<form data-bind="submit: doSomething">
... form contents go here ...
<button type="submit">Submit</button>
</form>
The "enable" binding
The enable binding causes the associated DOM element to be enabled only when the parameter value is true.
<p>
<input type='checkbox' data-bind="checked: hasCellphone" />
I have a cellphone
</p>
<p>
Your cellphone number:
<input type='text' data-bind="value: cellphoneNumber, enable: hasCellphone" />
</p>
The "disable" binding
The disable binding causes the associated DOM element to be disabled only when the parameter value is true. This is useful with form elements like input, select, and textarea.
This is the mirror image of the enable binding.
The "value" binding
The value binding links the associated DOM element’s value with a property on your view model. This is typically useful with form elements such as <input>, <select> and <textarea>.
<p>Login name: <input data-bind="value: userName" /></p>
<p>Password: <input type="password" data-bind="value: userPassword" /></p>
The "checked" binding
The checked binding links a checkable form control — i.e., a checkbox (<input type='checkbox'>) or a radio button (<input type='radio'>) — with a property on your view model.
<p>Send me spam: <input type="checkbox" data-bind="checked: wantsSpam" /></p>
The "options" binding
The options binding controls what options should appear in a drop-down list (i.e., a <select> element) or multi-select list (e.g., <select size='6'>). This binding cannot be used with anything other than <select> elements.
The value you assign should be an array . The <select> element will then display one item for each item in your array.
<p>
Destination country:
<select data-bind="options: availableCountries"></select>
</p>
Rendering templates
The "template" binding
The template binding populates the associated DOM element with the results of rendering a template.
<h2>Participants</h2>
Here are the participants:
<div data-bind="template: { name: 'person-template', data: buyer }"></div>
<div data-bind="template: { name: 'person-template', data: seller }"></div>
<script type="text/html" id="person-template">
<h3 data-bind="text: name"></h3>
<p>Credits: <span data-bind="text: credits"></span></p>
</script>
Observables
How can KO know when parts of your view model change?
You need to declare your model properties as observables, because these are special JavaScript objects that can notify subscribers about changes, and can automatically detect dependencies.
var workshop = {
id: 104,
title: ko.observable('Vehicle Design: Sci-Fi Ship'),
author: ko.observable('Paul Christopher'),
price: ko.observable(39.99)
};
View with observables
<p>Title: <input data-bind="value: title"></p>
<p>Author: <input data-bind="value: author, valueUpdate: 'afterkeydown'"></p>
<p>Price: <input data-bind="value: price"></p>
<h2>
<!-- ko text: title --><!-- /ko -->
<small data-bind="text: '(by ' + author() + ')'"></small>
</h2>
<p>Price: $<!-- ko text: price --><!-- /ko --></p>
Example link.Reading and writing observables
ko.observable objects are actually functions.
-
To read the observable’s current value, just call the observable with no parameters. In this example:
workshop.title(); // return 'Vehicle Design: Sci-Fi Ship'
- To write a new value to the observable, call the observable and pass the new value as a parameter:
workshop.title('Vehicle Design: Sci-Fi Ship 2'); // change the title to 'Vehicle Design: Sci-Fi Ship 2'
Computed Observables
Workshop = function () {
var _this = this;
//...
_this.price = ko.observable(39.99);
_this.discount = ko.observable(10);
_this.priceWithDiscount = ko.computed(function () {
return this.price() - this.price() * (this.discount() / 100)
}, _this);
};
ko.applyBindings(new Workshop);
KnockoutJs
By Aleksej Romanovskij
KnockoutJs
- 1,446