Chapter 1. Getting Started with KnockoutJS

KnockoutJS is an open source JavaScript library. It was built to allow you to create dynamic and rich web applications. It is built with the Model-View-ViewModel (MVVM) pattern. Knockout makes it really simple to implement a complex user interface that responds to user interactions.

I like Knockout because it is one of the most lightweight JavaScript libraries available today. It also doesn’t try to be an all-in-one framework. It serves a single purpose: data binding your ViewModel to your user interface.

Implementing Knockout involves three distinct things: a view that contains HTML and CSS elements that get data-bound to it, a ViewModel that contains the data to bind to the view, and telling Knockout to perform the data binding to the view with the ViewModel.

The examples in this chapter demonstrate how to create an HTML page with a basic ViewModel. After we review the basic data binding syntax, we will explore the various types of ViewModels that work with the view.

Data Binding Syntax

Data binding is accomplished by adding an HTML attribute called data-bind to any HTML element that you want Knockout to replace with information from your ViewModel.

Sometimes an HTML tag does not work, so Knockout also allows you to specify data bindings with HTML comments, as shown in Example 1-1.

Example 1-1. Knockout bindings using HTML comments
<!-- ko -->
<!-- /ko -->

Binding through HTML comments is extremely convenient when you want to wrap your binding around a block of HTML code, or you do not want to create an extra HTML object for the sole purpose of housing a data binding.

Data Binding Example

One of the most common things that Knockout is used for is to dynamically display text or HTML based on data contained within a ViewModel.

Example 1-2 shows creating a header that will display the name property within the ViewModel.

Example 1-2. Data binding text
<!DOCTYPE html>
<html>
<head>
    <title>Data Binding with KnockoutJS</title>
</head>
<body>
    <h1>Hello <span data-bind="text: name"></span></h1>

    <script type='text/javascript' src='js/knockout-3.2.0.js'></script> 
    <script>
        var viewModel = function() { 
            this.name = 'Steve Kennedy';
        }; 

        ko.applyBindings(viewModel); 
    </script>
</body>
</html>

When this example is executed in a browser, it outputs Hello Steve Kennedy inside an h1 tag.

A span tag is data-bound to the name property of the ViewModel. This is done by placing text: name inside the data-bind HTML attribute.

As mentioned in the introduction to this chapter, implementing Knockout requires three distinct things. The first is the view, which in this example is the HTML that contains the h1 and span tags that identify the data binding.

The second is the ViewModel, which in this example is the JavaScript variable/function called viewModel that contains a single variable name.

The third is telling Knockout to perform the data binding of the view and the ViewModel. This is accomplished by calling the ko.applyBindings function with a ViewModel.

When this function is executed, Knockout processes both the view and the ViewModel. All data bindings in the view are executed and dynamically replaced with the data from the ViewModel.

Knockout does not limit you to a single ViewModel per view. Large projects or classes that are well designed for reusability are common reasons to bind multiple ViewModels to a single view. This is discussed in more detail in Chapter 6.

What Is MVVM

The Model-View-ViewModel (MVVM) design pattern is based largely on the Model-View-Controller (MVC) pattern. In fact, the MV is shared between them. It’s the ViewModel that really separates the two.

MVVM was designed to implement data binding between your ViewModel and your View. This is what KnockoutJS does for us and does very well. It is accomplished using some simple-to-implement HTML attributes and a JavaScript ViewModel as shown in Example 1-2.

The most important thing to remember when you are building ViewModels is that they should be organized to make it easy to represent how your View uses the data. We explore several common scenarios in the upcoming examples.

Creating a ViewModel

A ViewModel can be any type of JavaScript variable. In Example 1-3, let’s start with a simple JavaScript structure that contains a single property called name.

Example 1-3. Basic ViewModel
var myFirstViewModel = {
    name: 'Steve Kennedy'
};

The previous example is a perfect scenario of a ViewModel that might not correlate 100% to a data model. Frequently, a data model separates the first and last name into two separate fields to make editing the data easier. However, in a view, it makes more sense to concatenate them into a single field for display.

The previous ViewModel is quite basic. ViewModels are not limited to such a simple structure, as the next examples demonstrate.

Object-Oriented ViewModels

Typically, when I create ViewModels, I create simple or complex JavaScript classes that allow me to leverage an object-oriented style of programming (functions, properties, abstraction, etc.).

Object-Oriented Programming with JavaScript

JavaScript is a fully object-oriented programming (OOP) language based on prototyping. It doesn’t contain class statements like C++, C#, or PHP; however, JavaScript functions can be used to simulate the same behavior.

It also offers full support of OOP language features such as namespaces, objects, properties, inheritance, abstraction, etc.

If you are new to JavaScript or object-oriented programming, the Mozilla Developer Network (MDN) offers a great introductory article.

In Example 1-4, I create a ViewModel that is built with some basic object-orientation that will provide more functionality for our view.

Example 1-4. Object-Oriented ViewModel
var mySecondViewModel = function() {
    var self = this;
    
    self.name = 'Steve Kennedy';
    
    self.getName = function() {
        return self.name;
    };
};

In this example, my ViewModel is a JavaScript function that I’ve made to act like a class in OOP. It contains the same name variable that I created in the previous example, but this time it is encapsulated in my class and acts like a property of it.

I also added a new function called getName that allows me to access my name property without calling my class property directly from elsewhere in my code.

Self = This?

You may be wondering why the first line of my class is var self = this;. By creating a variable called self and assigning it the variable this, it provides me a property in my class that I can use inside methods of my class and easily reference other methods or properties in my class.

Even though the resulting code between Example 1-4 and Example 1-3 look quite different, in fact, they are quite similar. The name property can be accessed in the exact same way from either example, as shown in Example 1-5.

Example 1-5. Accessing the name property
alert(myFirstViewModel.name);
 
alert(mySecondViewModel.name); // access the property name
alert(mySecondViewModel.getName()); // access the function getName

All three of the previous statements will alert name.

ViewModels with Parameters

In Examples 1-3 and 1-4, the name property was hardcoded to a value. In many scenarios, data like this would be populated from a different source: a database, the results of an AJAX call, etc.

In Example 1-6, the name will be populated via an input to the ViewModel.

Example 1-6. A ViewModel with a parameter
function ViewModel(name) { 
    var self = this; 
    
    self.name = name; 
    
    self.getName = function() { 
        return self.name; 
    }; 
}; 

var myThirdViewModel = new ViewModel('Steve Kennedy');

In Examples 1-3 and 1-4, the ViewModel class was assigned directly to the variable. This example is slightly different in that a function (acting like a class) called View Model is created that accepts the name property. This class is then instantiated by passing the name into the constructor.

In all future examples, I will continue to use JavaScript classes as they provide a lot more flexibility. However, if a simple JavaScript variable or structure will suffice for your view, do not feel the need to wrap your ViewModel in a class.

Get Knockout.js now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.