JavaScript library that helps you to create rich, responsive display and editor user interfaces with a clean underlying data model.
Just declare any JavaScript object:
var workshop = {
id: 104,
title: 'Vehicle Design: Sci-Fi Ship',
author: 'Paul Christopher',
price: 39.99
};
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>
To activate Knockout, add the following line to a JS code:
ko.applyBindings(workshop);
<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>
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">
<!-- 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>
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 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 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 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 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 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>
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 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>
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 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>
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 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 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 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 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 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 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 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>
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>
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)
};
<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.ko.observable objects are actually functions.
workshop.title();
// return 'Vehicle Design: Sci-Fi Ship'
workshop.title('Vehicle Design: Sci-Fi Ship 2');
// change the title to 'Vehicle Design: Sci-Fi Ship 2'
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);