MILANO 1863 POLITECNICO Knockout.js AN MVVM FRAMEWORK FOR JAVASCRIPT Carlo Bernaschina – [email protected]
MILANO 1863 POLITECNICO
Knockout.js AN MVVM FRAMEWORK FOR JAVASCRIPT
Carlo Bernaschina – [email protected]
MVVM MODEL VIEW VIEW-MODEL
• Model it is responsible of managing the domain model data and abstracting from the
data access layer.
• ViewModel it is an abstraction of the View, it communicates with the model and exposes
data and actions, that can be read, written and invoked by the View. Actions
are the implementation of the application’s use cases. View and ViewModel
are loosely coupled. It is possible to pair a View with a ViewModel as long as
they share a common set of exposed data and actions.
• View it defines how the data is going to be visualized and can invoke actions.
• Binder (hidden in the framework) it is responsible to synch View and ViewModel.
MVVM MODEL VIEW VIEW-MODEL
While MVC is the de-facto standard for Server-side
applications, MVVM is gaining more and more traction
on the Client side.
More and more frameworks are based on this
paradigm:
• WPF
• Knockout.js
• Polymer
• …
MVVM MODEL VIEW VIEW-MODEL
Knockout.js is an open-source lightweight MVVM
framework for JavaScript.
It includes the following features:
• Declarative bindings
• Automatic UI refresh
• Dependency tracking
• Templating
Knockout.js
In Knockout.js a ViewModel is just a JavaScript object
function ViewModel() {
this.firstName = 'John';
this.lastName = 'Doe';
}
Once created, the bindings on the current DOM can be initialized by the following call.
ko.applyBinding(new ViewModel());
Knockout.js WHAT IS A VIEW-MODEL?
Knockout.js allows to define bindings between DOM
elements and the ViewModel with a declarative syntax.
<p>FirstName: <span data-bind="text: firstName"></span></p>
<p>LastName <span data-bind="text: lastName"></span></p>
The data-bind attribute allows to define these bindings.
Knockout.js DECLARATIVE BINDINGS
Knockout.js allows to automatically update the UI when the ViewModel changes.
function ViewModel() {
this.firstName = ko.observable('John');
this.lastName = ko.observable('Doe');
}
An observable is an element of the ViewModel that notifies when its value changes. The binder listen for notifications and update the UI accordingly.
Knockout.js AUTOMATIC UI REFRESH
The binding can be two-way. Changes in the
ViewModel update the UI while changes in the UI
update the ViewModel back.
<p>FirstName: <input type="text" data-bind="value: firstName"></input></p>
<p>LastName: <input type="text" data-bind="value: lastName"></input></p>
<p>Hello
<span data-bind="text: firstName"></span>
<span data-bind="text: lastName"></span>
</p>
Knockout.js AUTOMATIC UI REFRESH (2)
The ViewModel can expose “computed” observables. Their value is based on others. The framework keep track of these dependencies while updating the UI. (See Computed Observables)
function ViewModel() {
this.firstName = ko.observable(‘John');
this.lastName = ko.observable('Doe');
this.fullName = ko.computed(function () {
return this.firstName() + ' ' + this.lastName();
});
}
<p>Hello <span data-bind="text: fullName"></span></p>
Knockout.js DEPENDENCY TRACKING
Kockout.js has a native template engine that allows to dynamically compute the page’s DOM based on data available in the ViewModel
<ul data-bind="foreach: collection">
<li data-bind="text: value"></li>
</ul>
In this example the template engine will add an item for each element in the collection and will add a value to that item based on the corresponding element.
Knockout.js TEMPLATING
Observables are special JavaScript objects that can
notify subscribers about changes.
There are 3 different types of Observables:
• “standard” Observables
• Observables Arrays
• Computed Observables
Observables
A “standard” observable can be defined in the following way.
var obs = ko.observable(<default value>);
The observable will be initialized with the default value and is ready for work.
Read and write operations on the observable can be performed with the following syntax.
obs(); // read
obs(<new value>); // write
Observables “STANDARD”
An observable array is an array that notifies when values are added or removed from it. It can be defined in the following way.
var obs = ko.observableArray(<default array value>);
The observable will be initialized with the default value and is ready for work.
The observable exposes standard array operations like
push | pop | shift | unshift | slice | splice | …
Observables ARRAY
A computed observable does not store its value, but can be recomputed when needed. It can be defined in the following way.
var obs = ko.computed(function () {
return … // compute routine
});
The framework is responsible to identify all the observables that are used in the computation of a computed one. When one of them changes a change is notified for all the computed observables that depend on it.
Observables COMPUTED
A writable computed observable does not store its value, but allow one to react to a write operation. It can be defined in the following way.
var obs = ko.computed({
read: function () {
return … // compute routine
},
write: function (value) {
// update status
}
});
Observables COMPUTED - WRITABLE
Bindings are relations between elements of the View and data or actions exposed by the ViewModel.
They are defined via a special attribute “data-bind” on a DOM element.
Syntax:
<dom_element data-bind="…">…</dom_element>
data-bind="binding: expression, binding: expression, …"
Bindings
Binding expressions are of 3 types:
• Parameter "binding: parameter" (e.g. "text: message")
the parameter will be identified in the ViewModel and a binding will be
set.
• Action "binding: action" (e.g. “click: addMessage")
the action in the ViewModel will be identified and when the event is
triggered the action will be invoked.
• Expression "binding: expession" (e.g. "text: message() + ' tail '")
the expression will be analized and all the observables registered. This
will allow only one way binding.
Bindings EXPRESSIONS
While it is possible to define custom bindings there are
many predefined ones:
• Text & Appearance
• Form
• Control Flow (templating)
Bindings PREDEFINED
The following bindings relate to the content of a DOM element.
• visible controls the visibility of the element
• text allow one to change the content of the element (html entities will be
escaped)
• html allow one to change the content of the element (html entities will NOT be
escaped)
Bindings TEXT & APPEARANCE
The following bindings are related to and object of the form
{ name1: expression, name2: expression2, …}
• css all the properties will be evaluated as expressions and if an expression
evaluates to true that property name will be added to the class attribute of
the DOM element
• style all the properties will be evaluated as expressions and the css rule with
the same name of the property will be set to that value
• attr all the properties will be evaluated as expressions and the attribute of the DOM
element will the same name of the property will be set to that value
Bindings TEXT & APPEARANCE (2)
Form inputs have a series of special bindings that refer to
attributes or events:
• value the value of the input field
• textInput same as value, but will be updated at each keystroke
• click the action will be invoked when the element is clicked
• submit the action will be invoked when the form is going to be submitted
• …
Bindings FORM
Via Bindings is possible to define dynamic templates.
Some primitives are:
• foreach the content of the current element is a template for the representation of
each item of the related collection
• if the content of the current element is removed from the DOM if the
expression evaluates to false
• ifnot the opposite of if
• with the current context changes from the ViewModel to a particular property
Bindings CONTROL FLOW
Let’s make an example of foreach binding.
ViewModel:
this.items = ko.observableArray([{message: 'element 0', color: 'red'},
{message: 'element 1', color: 'green'}]);
View:
<ul data-bind="foreach: items">
<li data-bind="text: message, style: {color: color}"></li>
</ul>
After binding:
Bindings FOREACH
• element 0
• element 1
• http://stackoverflow.com/questions/667781/what-is-
the-difference-between-mvc-and-mvvm
• https://commons.wikimedia.org/wiki/File:MVVMPatte
rn.png
• http://knockoutjs.com/documentation
Reference