Sign In Start Free Trial
Account

Add to playlist

Create a Playlist

Modal Close icon
You need to login to use this feature.
  • Book Overview & Buying MASTERING KNOCKOUTJS
  • Table Of Contents Toc
MASTERING KNOCKOUTJS

MASTERING KNOCKOUTJS

By : Moran
4.7 (6)
close
close
MASTERING KNOCKOUTJS

MASTERING KNOCKOUTJS

4.7 (6)
By: Moran

Overview of this book

If you are an experienced JavaScript developer who is looking for new tools to build web applications and get an understanding of core elements and applications, this is the book for you. A basic knowledge of DOM, JavaScript, and KnockoutJS is assumed.
Table of Contents (11 chapters)
close
close
10
Index

Defining viewmodels

Viewmodels are the objects whose properties your view binds with; they form the binding context. It is the representation of your data and operations for your view (we will cover them in detail in the Control flow bindings section later in this chapter). Like regular objects in JavaScript, there are many ways to actually create them, but Knockout introduces some specific challenges.

The this and self keywords

In JavaScript, this has a special meaning; it refers to the object calling the function. Functions called from an object get that object set to this. However, for functions that are anonymously called by code, that is merely the inside of an object, the behavior is different. Consider the following viewmodel:

function Invoice() {
  this.subtotal = ko.observable();
  this.total = ko.computed(function() {
  return this.subtotal() * 1.08; //Tax Rate
  });
}

The function inside the computed observable is not a property of the Invoice object. As it runs in a different context, its value for this will be the window object, not the Invoice object. It will not be able to find the subtotal property. There are two ways to handle this.

The first is by using the second parameter of the ko.computed function to bind the function to this:

function Invoice() {
  this.subtotal = ko.observable();
  this.total = ko.computed(function() {
    return this.subtotal() * 1.08; //Tax Rate
  }, this);
}

This gives the computed observable a reference to the Invoice that originally defined it, which allows the computed observable to call the supplied function in the correct context.

The second way to ensure the computed observable can reference the subtotal, is to capture the value of this in a closure. You can then use the closure to safely refer to the properties of the parent viewmodel. There are several conventional names for such a closure: that, _this, or self.

I prefer to use self as it is visually distinct from this while still carrying a similar meaning, but it's up to you:

function Invoice() {
  var self = this;
  self.subtotal = ko.observable();
  self.total = ko.computed(function() {
return self.subtotal() * 1.08; //Tax Rate
  });
}

I find the second method easier to remember. If you always use self to refer to the model, it will always work. If you have another anonymous function inside the computed, you will have to remember to bind that function as well; self continues to work as a closure no matter how many levels deep you nest. The self variable works as a closure inside any function defined in your viewmodel, including subscriptions. It's also easier to spot when self isn't being used, which is very helpful while debugging your code.

Problems with prototypes

If you are working with viewmodels that will be inherited by other viewmodels, you might think that putting all the base observable properties on the prototype is the way to go. In vanilla JavaScript, if you are inheriting an object, try to change the value of a property stored on the prototype; the property would be added to the inheriting object leaving the prototype intact. When using observables in Knockout though, this isn't the case. The observables are functions, and their values are set by calling them with a single parameter, not by assigning new values to them. Because prototypical inheritance would result in multiple objects referring to a single observable; observables cannot be safely placed on viewmodel prototypes. Nonobservable functions can still be safely included in prototypes. For example, consider the following objects:

var protoVm = {
  name: ko.observable('New User')
};

var base1 = Object.create(protoVm);
var base2 = Object.create(protoVm);

base2.name("Base2");

The last line will cause the name of both objects to be updated, as it is referring to the same function. This example can be seen in the cp1-prototype branch, which includes two input elements bound to the name of each viewmodel. As they are really the same observable, changing one will affect the other.

Serializing viewmodels

When you are ready to send your viewmodels to the server, or really do anything that requires you to work with their values instead of observables, Knockout provides two very handy utility methods:

  • ko.toJS: This function takes an object and does a deep copy, unwrapping all observables, into a new JavaScript object whose properties are normal (nonobservable) JavaScript values. This function is perfect to get copies of viewmodels.
  • ko.toJSON: This function uses the output from ko.toJS with JSON.stringify to produce a JSON string of the supplied object. This function accepts the same parameters as JSON.stringify.
CONTINUE READING
83
Tech Concepts
36
Programming languages
73
Tech Tools
Icon Unlimited access to the largest independent learning library in tech of over 8,000 expert-authored tech books and videos.
Icon Innovative learning tools, including AI book assistants, code context explainers, and text-to-speech.
Icon 50+ new titles added per month and exclusive early access to books as they are being written.
MASTERING KNOCKOUTJS
notes
bookmark Notes and Bookmarks search Search in title playlist Add to playlist font-size Font size

Change the font size

margin-width Margin width

Change margin width

day-mode Day/Sepia/Night Modes

Change background colour

Close icon Search
Country selected

Close icon Your notes and bookmarks

Confirmation

Modal Close icon
claim successful

Buy this book with your credits?

Modal Close icon
Are you sure you want to buy this book with one of your credits?
Close
YES, BUY

Submit Your Feedback

Modal Close icon
Modal Close icon
Modal Close icon