Beginners Guide to KnockoutJS: Part 2

Ivaylo Gerchev

A Beginners Guide to KnockoutJS: Bindings

Knockout provides a whole set of useful built-in bindings for the most common tasks and scenarios. Each of these bindings allows you to bind simple data values or use JavaScript expressions to calculate the appropriate value. This provides a lot of flexibility and makes it easy to create very dynamic UIs with minimum effort.

The syntax for using the built-in bindings is to include the Knockout binding name and the view model property pairs inside of the data-bind attribute of an HTML element.

// syntax: data-bind="bindingName: bindingProperty"
<span data-bind="text: msg"></span>

If you want to data bind to more than one property in the HTML element, simply separate the bindings by a comma using this syntax:

<span data-bind="text: msg, visible: toggle"></span>

You should bear in mind that the most of the bindings attempt to convert any parameter to a boolean value. If you give a value that isn’t actually boolean, it will be interpreted loosely. This means that nonzero numbers and non-null objects and non-empty strings will all be interpreted as true, whereas zero, null, undefined, and empty strings will be interpreted as false.

If you understand how to use one type of data binding, then the others should be pretty easy to learn. Now we are going to explain each one of them by providing a description and short example.

Simple Bindings

We’ve already seen text binding when dealing with observables in the previous tutorial. It sets the text of the associated element to the value of your parameter. This is the equivalent of setting the innerText(for IE) or textContent (for other browsers) property of the DOM element. If your parameter is something other than a number or string then the binding will assign the results of toString() to the element.

If this parameter is an observable value, the binding will update the element’s text whenever the value changes. If the parameter isn’t observable, it will only set the element’s text once and will not update it again later. This is valid for all bindings.

The text binding is often used to display values in a span or div element. When it is used, any previous text will be overwritten.

<p>The tip of the day is: <span data-bind="text: tipOfTheDay"></span></p> 

function viewModel() {
 var self = this;
 self.tipOfTheDay = ko.observable('Relax.Take it easy!')
};
ko.applyBindings(new viewModel());

value binding sets the value of the associated element to the value of your parameter. This is typically used for form elements like input, select and textarea. When the user edits the value in the associated form control, it updates the value on your view model. Likewise, when you update the value in your view model, this updates the value of the form control on screen. This is known as two-way binding. If your parameter is something other than a number or string then the binding will assign the results of toString() to the element.

By default, Knockout updates your view model when the user transfers focus to another DOM node, on the change event, but you can control when the value is updated using the valueUpdate parameter described below. If your binding also includes a parameter called valueUpdate, this defines which browser event Knockout should use to detect changes.

"change" is the default event and it updates your view model when the user moves the focus to a different control, or in the case of <select> elements, immediately after any change.

"afterkeydown" – updates your view model as soon as the user begins typing a character. This works by catching the browser’s keydown event and handling the event asynchronously. If you want to keep your view model updated in real-time using "afterkeydown" will be the best choice.

"keyup" – updates your view model when the user releases a key

"keypress" – updates your view model when the user has typed a key. This updates repeatedly if the user holds a key down

<input data-bind="value: name, valueUpdate: 'afterkeydown'"></input>
<p data-bind="text: name"></p>

function viewModel() {
 var self = this;
 self.name = ko.observable()
};
ko.applyBindings(new viewModel());

Control Mark Up

The html binding isn’t used as often, but it’s very handy for rendering HTML content in your view model. This binding sets the HTML of the associated element to the value of your parameter and is the equivalent of setting the innerHTML property on the DOM element. If your parameter is something other than a number or string then the binding will assign the results of toString() to the element.

Since this binding sets your element’s content using innerHTML, you should be careful not to use it with untrusted model values, because that might open the possibility of a script injection attack. If you cannot guarantee that the content is safe to display, then you can use the text binding instead.

<div data-bind="html: markup"></div>

function viewModel() {
 var self = this;
 self.markup = ko.observable('<p><strong>Knockout</strong> is so <em>cool</em>!</p>')
};
ko.applyBindings(new viewModel());

While Knockout has many built-in bindings, you will surely encounter some situations for which none exist. For those, Knockout offers the attr binding, which allows you to data bind any attribute to a view model property. The parameter should be a JavaScript object where the property names are the attributes and the property values are the value that will be bound to the attribute. This is very useful in many common scenarios, such as binding the href and title of the a element or the src and alt of the img element.

<img data-bind="attr: {src: url, alt: details}" />

function viewModel() {
 var self = this;
 self.url = ko.observable(images/logo.png)
 self.details = ko.observable('This is logo')
};
ko.applyBindings(new viewModel());

Add Styling

You can bind styles with Knockout using the css and the style built-in bindings.

css binding sets one or more CSS classes for the associated element. The parameter should be a JavaScript object where the property names correspond to the desired CSS classes and the property values evaluate to true or false indicating whether the class should be applied. You can set multiple CSS classes at once.

<style>
.colorize {color: red}
</style>

<p data-bind="css: { colorize: on }">Text</p>

function viewModel() {
 var self = this;
 self.on = ko.observable(true)
};
ko.applyBindings(new viewModel());

You can use an expression to determine when the class will be applied.

<p data-bind="css: { colorize: on() > 3 }">Text</p>

While it is better to use css classes whenever possible, at times you might want to set a specific style as well. Knockout supports this with its style built-in binding which sets one or more style values for the associated element. The parameter should be an object whose properties correspond to CSS styles names, and the values correspond to the style values you wish to apply. Typically this parameter value is declared using JSON.

<p data-bind="style: {color: on() > 3 ? 'red' : 'black'}">Text</p>
function viewModel() {
 var self = this;
 self.on = ko.observable(5)
};
ko.applyBindings(new viewModel());

Note: When you have an attribute or CSS class whose name is not legal JavaScript variable name then you should wrap the identifier name in quotes so that it becomes a string literal. And if you want to apply style whose name isn’t a legal JavaScript identifier, you must use the JavaScript name for that style.

//incorrect:
<div data-bind="attr: { data-something: someValue }">...</div>
<div data-bind="css: { my-class: someValue }">...</div>
<div data-bind="style: { font-weight: someValue }">...</div>

//correct:
<div data-bind="attr: { 'data-something': someValue }">...</div>
<div data-bind="css: { 'my-class': someValue }">...</div>
<div data-bind="style: { fontWeight: someValue }">...</div>

Handling Events

Knockout supports binding to any event through its event built-in binding. It adds event handlers for the specified events to the associated DOM element. You can use this to bind to any defined HTML events. Within your event handler you can access the current view model data item, the event object, or even custom parameters passed as part of the event binding. To use event binding, you pass an object literal containing name value pairs for the event name and the view model method, separated by commas.

<p data-bind="event: { mouseover: hello, mouseout: goodbye }"> Mouse over me! </p>
<p data-bind="text: helloEnabled"></p>
<p data-bind="text: goodbyeEnabled"></p>

function viewModel() {
var self = this;
self.helloEnabled = ko.observable()
self.goodbyeEnabled = ko.observable()
 self.hello = function() {
 self.helloEnabled('Hello!');
 self.goodbyeEnabled('');
 }
 self.goodbye = function() {
 self.goodbyeEnabled('Goodbye!');
 self.helloEnabled('');
 }
};
ko.applyBindings(new viewModel());

click binding, as you may guess, is handling the click event. Because it is the most-used binding for events, it’s simply a shortcut to the event binding.

<button data-bind="click: writeMSG">Show</button>
<p data-bind="text: msg"></p>

function viewModel() {
 var self = this;
 self.msg = ko.observable()
 self.writeMSG = function() {
 self.msg('Hello!')
 }
};
ko.applyBindings(new viewModel());

submit binding is a shortcut for handling the submit event for the form element. When you use the submit binding on a form, Knockout will prevent the browser’s default submit action for that form. In other words, the browser will call your handler function but will not submit the form to the server. This is a useful default because when you use the submit binding, it’s normally because you’re using the form as an interface to your view model, not as a regular HTML form. If you do want to let the form submit like a normal HTML form, just return true from your submit handler.

Instead of using submit on the form, you could use click on the submit button. But using submit binding gives you the benefits of using alternative ways to submit the form, such as pressing the enter key while typing into a text box.

Controling UI

visible binding sets the visibility of the associated element based on the binding parameter value. The binding attempts to convert any parameter to a boolean value. Knockout’s visible binding should be bound to a property that evaluates to true or false. This takes priority over any display style you’ve defined using CSS.

<button data-bind="click: show">Show Message</button>
<button data-bind="click: hide">Hide Message</button>
<p data-bind="visible: msg">Hello, Knockout!</p>

function viewModel() {
 var self = this;
 self.msg = ko.observable()
 self.show = function() {
 self.msg(true)
 }
 self.hide = function() {
 self.msg(false)
 }
};
ko.applyBindings(new viewModel());

enable/disable binding sets the disabled attribute on the associated element based on the supplied value. This is typically used for form elements like the input, select and textarea. Knockout provides built-in bindings to enable and disable input elements. The enable binding will enable the input element if the property it’s bound to evaluates to true, and will disable the element if it evaluates to false. The disable binding does the exact opposite

<input data-bind="value: val, valueUpdate: 'afterkeydown'">
<button data-bind="enable: val">Send</button>

function viewModel() {
 var self = this;
 self.val = ko.observable()
};
ko.applyBindings(new viewModel());

Knockout has a built-in binding named hasfocus that determines and sets which element has the focus. The hasfocus binding is handy when you want the focus to be set to a specific element on a form for example search form when visitor open the page

<input data-bind="value: val, hasfocus: on"> 
<button data-bind="enable: on">Send</button>
function viewModel() {
 var self = this;
 self.val = ko.observable()
 self.on = ko.observable(false)
};
ko.applyBindings(new viewModel());

Dealing with Checkboxes and Radio Buttons

Checkboxes can be data bound to Knockout’s checked binding. The checked binding should be bound to a property or expression that evaluates to true or false. Because the view model properties are defined as observables, the checkbox is updated when the source property changes. Likewise, when a user checks or unchecks the checkbox, the value is updated in the view model property. This binding sets the checked state of radio buttons and checkboxes. For checkboxes, the binding attempts to convert any parameter into a boolean value. For radio buttons, the binding compares the buttons value attribute to the binding parameter.

<p>Let me choose my favorite car: <input type="checkbox" data-bind="checked: car" /></p>
<div data-bind="visible: car">
 Preferred model:
 <div><input type="radio" name="modelsGroup" value="ferrari" data-bind="checked: model" /> Ferrari</div>
 <div><input type="radio" name="modelsGroup" value="lamborghini" data-bind="checked: model" /> Lamborghini</div>
 <div><input type="radio" name="modelsGroup" value="bugatti" data-bind="checked: model" /> Bugatti</div>
</div>

function viewModel() {
 var self = this;
 self.car = ko.observable(),
 self.model = ko.observable("lamborghini") // Initially selects Lamborghini
};
ko.applyBindings(new viewModel());

Creating Dropdown Lists

Dropdown lists have several important properties to load a list of items, display a value, use a different key value and store the user’s selection. Knockout provides a built-in binding for each of these. options binding sets the options which will appear in a drop-down list element. The value should be an array. This binding cannot be used with anything other than <select> elements. For a multi-select list, to set which of the options are selected, or to read which of the options are selected, use the selectedOptions binding. For a single-select list, you can also read and write the selected option using the value binding.

The options binding identifies a list of values to display, usually from an array property on the view model.

<p>Choose your destiny: <select data-bind="options: availableRoles"></select></p>

function viewModel() {
 var self = this;
 self.availableRoles = ko.observableArray(['an artist', 'an actor', 'an author'])
};
ko.applyBindings(new viewModel());

The selectedOptions binding controls which elements in a multi-select list are currently selected. When the user selects or de-selects an item in the multi-select list, this adds or removes the corresponding value to an array on your view model.

<p>Choose your destiny: <select data-bind="options: availableRoles, selectedOptions: selected" multiple="true"></select></p>

function viewModel() {
 var self = this;
 self.availableRoles = ko.observableArray(['an artist', 'an actor', 'an author'])
 self.selected = ko.observableArray(['an author'])
};
ko.applyBindings(new viewModel());

Sometimes you want to display one value in the dropdown list but use another value when a user selects an item from the list. Knockout’s built-in optionsText and optionsValue bindings help. The optionsText binding is set to the string name of the property to display in the dropdown list, from the options binding. The optionsValue binding is set to the string name of the property to bind to for the selected value of the item in the dropdown list. optionsCaption is useful when you don’t want to have any prticular option selected by default. This parameter set a text such as ‘Select an item…’ on top of the options list and show it when there isn’t any particular item selected.

<p>Locales: <select data-bind="options: locales, selectedOptions: selected, optionsCaption: 'Select your locale...', optionsText: 'country', optionsValue: 'code'"></select></p>
<p data-bind="text: selected"></p>

function viewModel() {
  var self = this;
  self.locales = [
   { country: 'USA', code: 'en_US' },
   { country: 'Spain', code: 'es_ES' },
   { country: 'French', code: 'fr_FR' }
  ]
  self.selected = ko.observableArray();
 }
ko.applyBindings(new viewModel()); 

And that’s all for this part, stay tuned for the finale, same time next week!

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • http://www.deathshadow.com deathshadow

    Yes, let’s encourage using made up attributes, bloated libraries that rely on other bloated libraries, using examples that basically appear to be doing CSS’ job without the fat bloated nonsense… RIGHT.

    I really pity anyone who falls for this malarkey.

    • Travis Spencer

      No offense, but I don’t agree with your comment Les or deathshadow.

      Les,

      jQuery and Knockout has two completely different functions. They don’t compete with each other at. In fact, they complement each other. I suggest you go through the tutorials on knockout’s website to get a feel for what Knockout can do. One of it’s biggest features, data-binding, may not be needed in all instances, but in cases where it is needed, knockout it truly useful. :-)

      deathshadow,

      Let’s see, HTML5 encourages the use of custom attributes, knockoutjs has no dependencies, using data-binding features in knockout to dynamically bind CSS to html elements (not always needed, but if done correctly can be very powerful…i.e. bind CSS classes to elements, not inline styles), both jQuery and knockout are considered lightweight. Seems like you need to do a little more research :-)

  • Les

    What you can do with this library you can still do with JQuery although possibly with more legwork I suspect however that’s not a problem considering the time required to learn yet another library to acheive much the same as you could do with JQuery anyway.

    Simply put I just don’t see any point in this library, really, JQuery got here first, is the most popular and influential Javascript framework by far, and there is decent documentation too so (again) I see no need for KnockOutJS.

  • sam

    Knockout is beyond awesome and I’d encourage anyone doing front-end work to do a bit more investigating before you jump to conclusions.

    Using only jQuery to handle all the UI for a heavy-data-driven web app quickly becomes a nightmare. Knocout’s data-binding amazing and fun to use once you get the hang of it.

    This part of the industry is rapidly changing and tools like Knockout are ushering in a new era of possibilities – get excited to learn something new.

    Great article and series – keep it up

  • Rishank

    Good job by u, Keep us enlightened with some more stuff .Any way I want to say just one thing,you made the things clear which is not in the official Knockout.js site.