Knockout view model binding variations to a page

January 29, 2013

Bind a viewModel to the whole page

There are many variations to write the view model in knockout, for example if we are using a simple object as a view model we will have some problems with *this, *we will examine the variations of how we would write our view model and why

First of lets start with a simple example and how to write a simple* view model* and bind it to the page

First name: <input type="text" data-bind="value: firstName" /> Last name:
<input type="text" data-bind="value: lastName" />
<h2>Hello, <span data-bind="text: fullName " />!</h2>

And the Javascript file

var User = function () {
  this.firstName = ko.observable('Nadeem')
  this.lastName = ko.observable('Khedr')
  this.fullName = ko.computed(function () {
    return this.firstName() + ' ' + this.lastName()
  }, this)
}
ko.applyBindings(new User())

This will bind our javascript view model to the whole html document and every variable in the databind attributes wil refer to a property of this one view model

Bind a viewModel to a partial part of the page

In the previous example we passed our viewModel to ko.applyBindings, this method take another parameter, which is the DOM element that we want to attach our viewModel to, In the next example we will attach two different & not related viewModels to different parts of our page

<div id="section1">
  First name: <input type="text" data-bind="value: firstName" /> Last name:
  <input type="text" data-bind="value: lastName" />
  <h2>Hello, <span data-bind="text: fullName " />!</h2>
</div>
<div id="section2">
  First name: <input type="text" data-bind="value: firstName" /> Last name:
  <input type="text" data-bind="value: lastName" />
  <h2>Hello, <span data-bind="text: fullName " />!</h2>
</div>
var User = function (firstName, lastName) {
  this.firstName = ko.observable(firstName)
  this.lastName = ko.observable(lastName)
  this.fullName = ko.computed(function () {
    return this.firstName() + ' ' + this.lastName()
  }, this)
}
ko.applyBindings(new User('Nadeem', 'Khedr'), $('#section1').get(0))
ko.applyBindings(new User('Phil', 'Joe'), $('#section2').get(0))

Bind a viewModel to the whole page and bind other viewModels to sections inside the page

In a more advanced scenario what we could want is to bind a viewModel to the whole page & sort of mini viewModels to different reusable components inside the page

In the previous example we cant define two html sections inside each other with different viewModels, they must be distinct, in another word we can’t define a master view model for all the page and a small view model for a part of that page because they will collide

A scenario that we would want exactly that

  • We want a master viewModel to our page (Layout)
  • We want a reusable viewModel for a sidebar that we could use in multiple pages (Partial View)

To achieve that what we will do is go to the parent of the sidebar and tell it stop binding the page viewModel to your descendant elements

so what will happen exactly is we will define a viewModel to the whole page without specifying a DOM element to attach it to, and another view model (maybe in another file) for only the sidebar and bind it to it

How to do that without getting errors that the properties in the sidebar doesn’t exists in the application viewModel

We will put a custom attribute on the sidebar container, the attribute will look like this

<div id="sidebarCont" data-bind="allowBinding: false"></div>

what this will do is tell the current view model attached to the document to stop binding itself to the descendant elements for the sidebarCont

the allowBinding is a custom bindingHandler that we defined and looks like this

ko.bindingHandlers.allowBindings = {
  init: function (elem, valueAccessor) {
    var shouldAllowBindings
    shouldAllowBindings = ko.utils.unwrapObservable(valueAccessor())
    return {
      controlsDescendantBindings: !shouldAllowBindings,
    }
  },
}

the above code is self explanatory all the magic happens with the controlsDescendantBindings

if you want to read more about bindingHandlers you can check this link


Nadeem Khedr

Written by Nadeem Khedr citizen of the world, you can find me on Twitter & Github