Recently I started using KnockoutJS as a key component in my web development toolset. KnockoutJS has simplified my code while also allowing me to create richer web UIs. I have always disliked the amount of postbacks I was doing using a more traditional ASP.Net development approach. KnockoutJS eliminates many of the pain points associated with ASP.Net development and lends itself to a more modern AJAX based style of development. In this series of articles I’ll discuss some of the basics of developing ASP.Net applications using KnockoutJS. In future articles I’ll walk through some of the more advanced features of KnocktoutJS and show how you can use it in your DotNetNuke development.
MVVM for JavaScript
KnockoutJS is a JavaScript framework that implements the MVVM design pattern to allow you to quickly bind your view-model data to your HTML. MVVM, like the MVP and MVC design patterns, provides a clean separation between the presentation logic, the data and the business logic. This separation simplifies automated testing of your business and data layers and can significantly reduce maintenance costs.
The MVVM pattern is used quite extensively in the WPF and Silverlight development communities. MVVM allows developers to focus on writing the data access and business logic independently of the UI development. With Knockout, designers can focus on writing the HTML and CSS (the view) while the developers focus on the data layer and business logic (the view model, model and web services).
Declarative Binding
One of the strengths of MVVM is that it promotes the use of declarative binding. In most JavaScript development, the code directly manipulates DOM elements which leads to a tight coupling between the code and the UI. Changing the DOM hierarchy or element IDs often results in broken code. With declarative binding, you are free to change the UI code without impacting the underlying application logic. Likewise, you can write the application code with a minimal understanding of how that code will be bound to the UI. Of course both the UI and JavaScript must be coded with a common understanding of the basic system requirements.
With KnockoutJS, you can bind data to a DOM element by including a data-bind attribute in the markup which specifies the data-binding to perform. The code never has any reference to the DOM structure so you can freely change the HTML without breaking your bindings. In the example below, I have a very simple view model consisting of the first name and last name. Calling the applyBindings method and passing in our view model tells Knockout to bind the specified model to our UI. You can even provide a DOM element if you only want to bind this view model to one part of your overall UI.
Using the data-bind attribute we can specify how to bind this view model to our UI. In this example, I am binding the model to the text of my html elements. (click on the various JSFiddle tabs to see the HTML, JavaScript and resultant view)
KnockoutJS includes several built-in binding types that you can use for data binding. 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. If you understand how to use one type of data binding, then the others should be pretty easy to learn.
Binding | Description |
text | This binding sets the text of the associated element to the value of your parameter. This is the equivelent of setting the innerText or textContent 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. |
html | This binding sets the HTML of the associated element to the value of your parameter and is the equivelent 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. |
value | This binding sets the value of the associated to the value of your parameter. This is typically used for form elements like the input, select and textarea. If your parameter is something other than a number or string then the binding will assign the results of toString() to the element. |
checked | 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. |
visible | This 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. |
enable | This 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. The binding attempts to convert any parameter to a boolean value. |
disable | This binding sets the disabled attribute on the associated element based on the supplied value and is a mirror image of the enable binding |
style | This binding sets one or more style values for the associated element. The parameter should be an object whose properties correspond to CSS styles. Typically this parameter value is declared using JSON. |
css | This 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. |
attr | This binding sets one or more attributes for the associated element. 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. |
options | This binding sets the options which will appear in a drop-down list element. The value should be an array. |
Two Way Data Binding with Observables
While simple data binding is nice, KnockoutJS provides a much more robust two-way data binding capability through the use of observables. In the example below I have modified the html to display two input boxes for first name and last name. I have modified the view model to use observables rather than simple data types for each of the view model properties.
When you run this example, you can see that changing the first name in the input box also changes the greeting. Regardless of whether the properties change as the result of user input or as the result of being changed in code, any UI element that is bound to an observable property will be updated.
Sometimes you need to perform binding against more complex data. Often it is some calculation based on more basic data. In my previous example I greeted the user by their first name. What if I wanted to include the full name in my greeting? I could have used two separate bindings which would have required me to include two span tags. Knockout handles this by including a special computed observable.
I have updated the example below to include a computed observable in my view model. I have also changed my model from a simple JavaScript object to a function. This makes it easier to use and will allow me to initialize the view model in later examples. You can find examples online that use both types of view models.
At this point you should have a basic understanding of how to using simple data binding with KnockoutJS. Take some time to play with the various JSFiddle examples to get a better understanding of how data binding works. In Part 2 of this series, I’ll explore how to do binding for behaviors and how to create your own custom bindings.
This article is cross-posted from my personal blog.