In Part 1 of this series I discussed the basics of data binding in KnockoutJS. In this post, I’ll dive a little deeper in the the binding behaviors of KnockoutJS and show how you can build really responsive web apps using client side development techniques.
While data binding is an important part of KnockoutJS development, it is only part of what makes KnockoutJS so attractive. KnockoutJS is a JavaScript based implementation of the MVVM design pattern which is a derivation of the Presentation Model as described by Martin Fowler. Martin Fowler sums up the Presentation Model like this:
The essence of a Presentation Model is of a fully self-contained class that represents all the data and behavior of the UI window, but without any of the controls used to render that UI on the screen. A view then simply projects the state of the presentation model onto the glass.
As Fowler explains, the Presentation Model class should represent both the data and the behavior which are then bound to the view. Let’s dive into how KnockoutJS handles binding behaviors to your HTML.
Binding Behavior
In MVVM applications users are interacting directly with the view. The view is responsible for displaying data and accepting user input. In HTML, this input will generate events which I can then use to trigger some logic. In the example below I have added a button to my previous example. When I click the button, I want the app to greet the user.
The problem with this approach is that it mixes my behavior with my view and the behavior code has no knowledge of the current application state as contained in my underlying view-model. Even if I extract my JavaScript into a separate function it still wouldn’t solve the problem with application state. What I really want is a clean way to bind the onClick event to some function which is part of my view-model. This is exactly what Fowler describes as the essence of the Presentation Model.
KnockoutJS solves this problem very cleanly using the data-bind attribute that we looked at previously. KnockoutJS includes three bindings that allow me to bind standard HTML events.
Binding | Description |
event | This binding 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. |
click | This binding is a shortcut for handling the click event. |
submit | This binding is a shortcut for handling the submit event for the form element. |
The previous example can be refactored to use the KnockoutJS click event binding.
Alternatively I could have written this using the generic event binding. In addition to using the generic event binding, I also took advantage of the data and event objects which get passed as part of the event handler parameters.
Custom Bindings
While event and data binding are pretty simple and straightforward there will be occasions where you want to create your own binding types. Maybe you want to create a shortcut binding to handle the Change or Focus events or maybe you want to create a binding which wraps a set of events with a custom behavior. All of this and more is possible with custom bindings. In fact all of the event and data bindings that I previously discussed are just bindings that are defined in the core KnockoutJS library but the methods used by the core library are exactly the same methods you’ll use to create your own bindings.
KnockoutJS bindings consist of two methods: init and update. Creating a binding is as simple as creating an object with these two methods and registering that object with KnockoutJS using ko.bindingHandlers as shown in the JavaScript tab below. Then you can use that new binding in your markup as shown in the html tab.
As a real world example, I often find that when using multi-line text editors that use a lot of screen real-estate for the text editor in order to have a nice editing experience. However, when my focus is on other form fields I don’t really need to use all that space. In one project I wanted to expand the text editor only when it had focus.
The init binding method is used for setting the initial state of the DOM elements and also for setting up an event handlers that might be needed to implement the behavior. As you can see in this case, I was the system to make certain UI changes whenever the element receives or loses focus. Based on these events I update the view model to reflect whether I am currently editing the field or not. When the view model biography.editing value changes as a result of the focus and blur events, then KnockoutJS will call the update method.
The update method is used for adding more complex binding logic to an element than you could do with standard bindings. For example, if I was only changing the CSS for the binding element, then I wouldn’t really need to use the update method. Instead I could use a style binding with a simple expression to determine whether I was currently editing the biography element or not. Your custom binding does not have to include both the init and update methods. Use one or both as it makes sense for your binding.
KnockoutJS bindings are an incredibly powerful mechanism for building client-side functionality. At this point you should have a basic understanding of how both data and behavior binding works within KnockoutJS. In the next post of this series I’ll take a look at control flow bindings available in KnockoutJS and show how those bindings can be used for even greater control. The control flow bindings are an integral part of the templating story which is a key part of any client side development toolkit.
This article is cross-posted from my personal blog.