Knockout.js – Bindings

Last time I introduced the basics of the knockout.js library. We looked at how you can declare a very simple model and then bind it to a UI using ‘data-bind’ attributes. I alluded to the fact that there are more bindings that come with knockout.js.

Simply put, a binding is something that ties some property (or method) to the HTML DOM. Some bindings are one-way and some are (or at least can be) two-way. In the last post we used the ‘text’ and ‘click’ bindings. ‘text’ can be a two-way binding. I say ‘can be’ because it can only be a two way binding if you initialize the bound model property using ko.observable(). If the bound property is initialized as a primitive javascript type (ie. string or number, etc), the binding will be one-way.

The real power of bindings comes into play when you start binding more than just text fields. Using bindings you can have the methods (behavior) on your javascript objects bound to different events on the DOM elements, such as ‘click’ or ‘event’. Using knockout bindings you can remove alot of that jQuery code to hook events and simply mark up your HTML with a few data-bind=”” attributes.

Let’s look at a small example. We’ll start with the model again:

var model = {
    firstName: ko.observable(""),
    lastName: ko.observable(""),
    submit: function() {
        var shouldSubmit = confirm("Are you really sure?");
        return shouldSubmit;
    }
}

model.isValid = ko.dependentObservable(function() {
    return this.firstName().length > 0 && this.lastName().length > 0;
}, model);

ko.applyBindings(model);

As you can see we have a couple of simple properties (firstName, lastName), but then we have two methods: isValid() and submit(). Let’s look at the HTML we’ll bind this too and then look at things more closely.

<form data-bind="submit: submit">
    First Name: <input type="text" data-bind="value: firstName" />
    Last Name: <input type="text" data-bind="value: lastName" />
    <input type="submit" data-bind="enable: isValid" />
</form>

Using bindings we’ve bound the two name fields to the text boxes. In addition we now can see what the user’s full name will be as soon as you tab out of either text field. You can also see that we disable the Submit button if either the first name or last name fields are empty. One trick here is that when you reference a ko.observable() field in your object and you want the underlying value, you call your field as a function (as we did in the isValid() method).

If you are interested you can play with the this example here: http://jsfiddle.net/tWM8r/2/

You can find out more about Knockout’s built-in bindings on the website here: http://knockoutjs.com/documentation/introduction.html

Knockout’s bindings will allow you to do most of what you need to do, and when you’re missing something, you can extend Knockout by writing your own custom bindings (something akin to writing a jQuery plugin). We’ll get into custom bindings in a future post.

That’s all for now. Next time we’ll look at Knockout’s template binding feature which is very powerful and useful.

Knockout.js – cleaning up the client-side

>I’ve started a new project with a client and it’s quite a shift for me. Coming off a heavy client (WinForms), 3-year project I’m now working in ASP.NET MVC and javascript. One of my goals with regards to the architecture was to keep a handle on the javascript. The project is integrating with the ESRI ArcGIS Javascript API and so there will be lots of client-side javascript and it will be important to keep it organized and maintainable.

In looking around for javascript libraries to help with this I found Knockout.js. This is a library for building larger-scale web applications that use javascript more heavily.

Knockout works by extending the properties of your javascript models (basically a POJO… Plain Old Javascript Object). You can then bind your model to the view (HTML elements) by marking up the HTML elements using “knockout bindings” (there are quite a few to choose from and they’re listed here). Basically a knockout binding is a way to bind a property on your model to a specific attribute of an HTML element. There are quite a few that come built into Knockout (including things like text, visible, css, click, etc).

Once you’ve got the view marked up you simply call

ko.applyBindings(model);

and Knockout takes it the rest of the way.

Let’s walk through a simple example as that’ll make things more clear (I’m going to use the same Login UI example as Derick Bailey used for his first Backbone.js post so it’s a bit easier to compare apples-to-apples… hopefully).

The layout is very similar to a Backbone view except that in a Knockout view you add extra ‘data-bind’ attributes.

Notice the ‘data-bind’ attributes in the markup. These dictate how knockout will bind the model we provide to the UI. Let’s move on to the model now.

This is very close to being a simple javascript object. The only trick is that any property that we want to bind to the UI should be initialized via the ko.observable() method. The value we pass to the ko.observable() will become the property’s underlying value.

Once we’ve instantiated a model object we simply call ko.applyBindings() and Knockout does the rest. (Note that the second parameter is the HTML element that should be the root of the binding. It is optional if you are only binding one object to your page, but I think in almost any application you’ll get to a point where you want to bind multiple objects so this shows how to do that.)

At this point Knockout will keep the UI and model in sync as we manipulate it. This is full 2-way binding for the text elements. So if the user types in the username field, the model’s username property is updated. If we update the model’s username property the UI will be updated as well.

Derick noted in his blog post the mixing of jQuery and Backbone.js. I’m doing some of that here, but I think Knockout.js doesn’t need jQuery as much because of how the binding is declared (on the HTML elements themselves).

I’m going to try to follow Derick’s excellent series of posts on Backbone.js and comment on how the subjects he discusses compare and contrast with Knockout.js.

In the end I think both are very capable libraries even if they come at the problem from slightly different angles. In the end it’s all about better organization of javascript and better assignment of responsibilities in the javascript you write.