Advertisement
JavaScript & AJAX

Hello, Knockout

by

This lesson is designed to be a high-level survey of Knockout.js’ main components. By implementing a concrete sample application, we’ll see how Knockout’s ViewModel, view, observables, and bindings interact to create a dynamic user interface.

First, we’ll create a simple HTML page to hold all of our code, then we’ll define a ViewModel object, expose some properties, and even add an interactive binding so that we can react to user clicks.


Download Knockout.js

Before we start writing any code, download the latest copy of Knockout.js from the downloads page at GitHub.com. As of this writing, the most recent version is 2.1.0. After that, we’re ready to add the library to an HTML page.


The HTML

Let’s start with a standard HTML page. In the same folder as your Knockout.js library, create a new file called index.html, and add the following. Make sure to change knockout-2.1.0.js to the file name of the Knockout.js library you downloaded.

Sample code: item1.htm

<html lang='en'>
<head>
  <title>Hello, Knockout.js</title>
  <meta charset='utf-8' />
  <link rel='stylesheet' href='style.css' />
</head>
<body>
  <h2>
  <p>Bill's Shopping Cart</p>

  <script src='knockout-2.1.0.js'></script>
</body>
</html>

This is a basic HTML 5 webpage that includes the Knockout.js library at the bottom of <body>; although, like any external script, you can include it anywhere you want (inside <head> is the other common option). The style.css style sheet isn’t actually necessary for any of the examples in this series, but it will make them much easier on the eyes. It can be found in Appendix A, or downloaded from https://bitbucket.org/syncfusion/knockoutjs_succinctly. If you open the page in a web browser, you should see the following:

Figure 8: Basic webpage

Defining the ViewModel

Since we’re not working with any persistent data yet, we don’t have a model to work with. Instead we’ll skip right to the ViewModel. Until Lesson 7:, we’re really just using a View-ViewModel pattern.

Figure 9: Focusing on the view and ViewModel for the time being

Remember, a ViewModel is a pure JavaScript representation of your model data. To start out, we’ll just use a native JavaScript object as our ViewModel. Underneath the <script> tag that includes Knockout.js, add the following:

<script>
  var personViewModel = {
    firstName: "John",
    lastName: "Smith"
  };

  ko.applyBindings(personViewModel);
</script>

</body>

This creates a “person” named John Smith, and the ko.applyBindings() method tells Knockout.js to use the object as the ViewModel for the page.

Of course, if you reload the page, it will still display “Bill’s Shopping Cart.” For Knockout.js to update the view based on the ViewModel, we need to bind an HTML element to the personViewModel object.


Binding an HTML Element

Knockout.js uses a special data-bind attribute to bind HTML elements to the ViewModel. Replace Bill in the <p> tag with an empty <span> element, as follows:

 <p><span data-bind='text: firstName'></span>'s Shopping Cart</p>

The value of the data-bind attribute tells Knockout.js what to display in the element. In this case, the text binding tells Knockout.js to display the firstName property of the ViewModel. Now, when you reload the page, Knockout.js will replace the contents of the <span> with personViewModel.firstName. As a result, you should see “John’s Shopping Cart” in your browser:

Figure 10: Screenshot of our first bound view component

Similarly, if you change the data-bind attribute to text: lastName, it will display “Smith’s Shopping Cart.” As you can see, binding an element is really just defining an HTML template for your ViewModel.


Observable Properties

So, we have a ViewModel that can be displayed in an HTML element, but watch what happens when we try to change the property. After calling ko.applyBindings(), assign a new value to personViewModel.firstName:

ko.applyBindings(personViewModel);
personViewModel.firstName = "Ryan";

Knockout.js won’t automatically update the view, and the page will still read “John’s Shopping Cart.” This is because we haven’t exposed the firstName property to Knockout.js. Any properties that you want Knockout.js to track must be observable. We can make our ViewModel’s properties observable by changing personViewModel to the following:

var personViewModel = {
  firstName: ko.observable("John"),
  lastName: ko.observable("Smith")
};

Instead of directly assigning values to firstName and lastName, we use ko.observable() to add the properties to Knockout.js’ automatic dependency tracker. When we change the firstName property, Knockout.js should update the HTML element to match:

ko.applyBindings(personViewModel);
personViewModel.firstName("Ryan");

Accessing Observables

You’ve probably noticed that observables are actually functions—not variables. To get the value of an observable, you call it without any arguments, and to set the value, you pass the value as an argument. This behavior is summarized as follows:

  • Getting: Use obj.firstName() instead of obj.firstName
  • Setting: Use obj.firstName("Mary") instead of obj.firstName = "Mary"

Adapting to these new accessors can be somewhat counterintuitive for beginners to Knockout.js. Be very careful not to accidentally assign a value to an observable property with the = operator. This will overwrite the observable, causing Knockout.js to stop automatically updating the view.


Using Custom Objects

Our generic personViewModel object and its observable properties work just fine for this simple example, but remember that ViewModels can also define methods for interacting with their data. For this reason, ViewModels are often defined as custom classes instead of generic JavaScript objects. Let’s go ahead and replace personViewModel with a user-defined object:

function PersonViewModel() {
  this.firstName = ko.observable("John");
  this.lastName = ko.observable("Smith");
};

ko.applyBindings(new PersonViewModel());

This is the canonical way to define a ViewModel and activate Knockout.js. Now, we can add a custom method, like so:

 function PersonViewModel() {
  this.firstName = ko.observable("John");
  this.lastName = ko.observable("Smith");
  this.checkout = function() {
    alert("Trying to check out!");
  };
};

Combining data and methods in a single object is one of the defining features of the MVVM pattern. It provides an intuitive way to interact with data. For example, when you’re ready to check out simply call the checkout() method on the ViewModel. Knockout.js even provides bindings to do this directly from the view.


Interactive Bindings

Our last step in this lesson will be to add a checkout button to call the checkout() method we just defined. This is a very brief introduction to Knockout.js’s interactive bindings, but it provides some useful functionality that we’ll need in the next lesson. Underneath the <p> tag, add the following button:

<button data-bind='click: checkout'>Checkout</button>

Instead of a text binding that displays the value of a property, the click binding calls a method when the user clicks the element. In our case, it calls the checkout() method of our ViewModel, and you should see an alert message pop up.

Figure 11: Alert message created after clicking the Checkout button

Knockout.js’ full suite of interactive bindings will be covered in Lesson 6:.


Summary

This lesson walked through the core aspects of Knockout.js. As we’ve seen, there are three steps to setting up a Knockout.js-based web application:

  1. Creating a ViewModel object and registering it with Knockout.js.
  2. Binding an HTML element to one of the ViewModel’s properties.
  3. Using observables to expose properties to Knockout.js

You can think of binding view elements to observable properties as building an HTML template for a JavaScript object. After the template is set up, you can completely forget about the HTML and focus solely on the ViewModel data behind the application. This is the whole point of Knockout.js.

In the next lesson, we’ll explore the real power behind Knockout.js’ automatic dependency tracker by creating observables that rely on other properties, as well as observable arrays to hold lists of data.

This lesson represents a chapter from Knockout Succinctly, a free eBook from the team at Syncfusion.

Related Posts
  • Code
    JavaScript & AJAX
    Animating KnockoutKnockoutjs
    Knockout.js is not an animation library. All of Knockout.js’ automatic updates are immediately applied whenever the underlying data changes. In order to animate any of its changes, we need to dig into Knockout.js’ internals and manually create animated transitions using another JavaScript framework like jQuery or MooTools. This lesson sticks with jQuery’s animation routines, but the concepts presented apply to other animation libraries as well.Read More…
  • Code
    JavaScript & AJAX
    Accessing External DataKnockoutjs
    For most web applications, collecting user input is relatively useless if you can’t pass that data along to a server. In this lesson, we’ll learn how to send and receive information from a server using AJAX requests. This puts the model back into the Model-View-ViewModel design pattern underpinning Knockout.js.Read More…
  • Code
    JavaScript & AJAX
    Interactive BindingsKnockoutjs
    Form elements are the conventional way to interact with users through a webpage. Working with forms in Knockout.js is much the same as working with appearance bindings. But, since users can edit form fields, Knockout.js manages updates in both directions. This means that interactive bindings are two-way. They can be set programmatically and the view will update accordingly, or they can be set by the view and read programmatically.Read More…
  • Code
    JavaScript & AJAX
    Appearance BindingsKnockoutjs
    In the previous lesson, we saw how Knockout.js’ control-flow bindings provide a basic templating system for view code. Control-flow bindings provide the visual structure for your application, but a full-fledged templating system needs more than just structure. Knockout.js’ appearance bindings give you precise control over the styles and formatting of individual elements.Read More…
  • Code
    JavaScript & AJAX
    Control-Flow BindingKnockoutjs
    As we’ve seen in previous lessons, designing a view for a ViewModel is like creating an HTML template for a JavaScript object. An integral part of any templating system is the ability to control the flow of template execution. The ability to loop through lists of data and include or exclude visual elements based on certain conditions makes it possible to minimize markup and gives you complete control over how your data is displayed.Read More…
  • Code
    JavaScript & AJAX
    Knockout ObservablesKnockoutjs
    We’ve seen how observable properties let Knockout.js automatically update HTML elements when underlying data changes, but this is only the beginning of their utility. Knockout.js also comes with two more ways of exposing ViewModel properties: computed observables and observable arrays. Together, these open up a whole new world of possibilities for data-driven user interfaces.Read More…