thoughts on coding

June 2, 2012

Observables and data-binding in action (Part III)

Filed under: Javascript, WWA — Tags: , , , — Frantisek @ 11:03 pm

Observables and their usage in binding

The typical scenario where observables’ features are leveraged is data-binding (binding the observable objects to html element – in other words model/viewmodel to view).

Declaration syntax

WinJS establish data-binding to UI in the following form:

<div data-win-bind="targetPropertyChain:sourcePropertyChain [customBindingFunction]" >

This was a declaration with the following meaning:

  • targetPropertyChain: declares a target of the databinding. It’s property name on the HTML element. Example: innerText. It supports also the chain of the properties, e.g. winControl.content.
  • sourcePropertyChain: declares a source of the databinding. It’s property name chain on an object (also called databinding context) whose data are used for binding. Example: address.street, name, etc.
  • customBindingFunction: it’s an optional parameter and declares a custom databinding function which replaces the default databinding function. There are several examples of it developed in MvvmJS. WinJS comes with two binding functions:
    1. default: it’s default oneway databinding function which binds a property from databinding context into a property on HTML element initialy and any time property on context object changes.
    2. onetime: it’s the function which bind the property from databinding context into element only once and only once.

Usage examples

<div data-win-bind="innerText:name" >

It’s the most simple binding use-case and declares binding from datacontext.name to targetElement.innerText.

<div data-win-bind="VISIBLE:isEmpty toggleClass" >

This defines the binding with the custom binding function defined as an extension in MvvmJS. The binding function toggleClass adds class VISIBLE to the element CSS class attribute in case datacontext.isEmpty is true.

<div data-win-bind="innerText:person.homeAddress.street" >

This defines binding street of the home address of the person accessible as a property on datacontext object to the innerText property on the target HTML element.

<div data-win-control="MvvmJS.UI.TemplateSelector" data-win-bind="winControl.content:person" >

First, it declares control MvvmJS.UI.TemplateSelector control (a custom WinJS UI control) over DIV. Then there is a databinding of datacontext.person to content property of winControl attribute set on the target DIV element. Note: it’s usual practice/pattern that UI control sets attribute winControl on the element to control instance.

Data-binding in action

That was just the first part of the story: declaration. Now, lets make the databinding alive.

WinJS introduces WinJS.Binding.processAll(root, dataContext, ..other parameters..) method which:

  1. searches for any element with data-win-bind attribute on the HTML element tree starting with root (optionaly skipping root) and
  2. then process the binding declarations.

WinJS.Binding.processAll method is usually called from JS page or fragment file.

Example

(function () {
    "use strict";

    WinJS.UI.Pages.define("/views/dummyView.html", {
        element: null,

        ready: function (element, options) {
            this.element = element;
            element.winControl = this;
            this.options = options;

            var vm = new MvvmJS.Samples.DummyVieModel();
            WinJS.Binding.processAll(element, vm);
        },
    });
}());

The example above is code-behind of the view DummyView which runs the binding processing in the ready event handler (raised when the page is rendered and ready to be used). In the ready event it instantiates DummyViewModel (please note a convention DummyView ~ DummyViewModel).

In case of an enterprise application it would be better to generalize the approach and define a base class with calling the binding process method from its ready method (this also brings MvvmJS).

Property chain subscriptions

There is one very usefull feature of WinJS databinding. WinJS databinding leverage observables and adds there property chain subscription of any property in sourcePropertyChain.

Let’s explain it on the example in BDD (behavior driven development) style:
Given: there is the following binding declaration

<div data-win-bind="innerText:person.address.street" >

When: person OR address OR street changes

Then: the binding is reprocessed and div’s innertext contains new value. This is very usefull feature in complex scenarios.

Comparing to manual approach

In case of manual approach it would be necessary to:

  1. initialy read the property and set the HTML element property with the value
  2. subscribe to any property chain change and handle the it with setting the new value

Manual approach implies more boilerplate and repetitive code which increase complexity of the result JS code.

In the next part we will look into custom binding method and extensions introduced in MvvmJS.

Create a free website or blog at WordPress.com.