WinRT JavaScript - Templates & Data Binding
Written by Ian Elliot   
Article Index
WinRT JavaScript - Templates & Data Binding
Templates and data
Data binding
The databound table

The Template object is useful in its own right, but add it to data binding and you have a easy-to-use way to present data to the user.  It also happens to be the easiest way to find out about data binding in general.

This article is Chapter 4 of  Creating JavaScript/HTML5 Metro Applications. In earlier chapters we looked at how to use WinJS custom controls. In this one we look at another one of the more interesting custom controls, the Template, and introduce the data binding mechanism.

 

The Template is useful whenever you need to create multiple copies of the same HTML and content.

You could, for example, use it to generate the lines in a table structure. This is useful but not super useful. However, if you add data binding to the Template object it all becomes so much more useful. With data binding you can not only "stamp out" lines in a table, you can also automatically fill them in.

The databound Template is a natural way to create any table or list of data automatically and with minimal fuss.

So let's get started.

It is assumed that you know how to work with a WinRT JavaScript project and know the basics of HTML/CSS, as described Chapter 1.  It is also assumed that you know how custom controls work, as described in Chapter 2.

The Template

The basic Template control is a very simple thing. All it does is to contain any HTML you care to fill it with. When the Template control is initialized its only action is to hide its contents.

This may sound like a strange thing to do but you don't want the Template itself showing on your page until you are ready to make a copy of it and place it where you want it.

Start a new blank project this loads all of the JavaScript libraries you will need.

Next we need to create a Template element using the standard approach introduced earlier, i.e. using the data- attribute.

As the template represented by the Template object is composed of whatever HTML you care to put between its tags, let's just use a Div with some dash characters to represent a horizontal line - not particularly useful but easy to understand.

Our Template in HTML is just:

<div id="Mytemplate" data-win-control=
"WinJS.Binding.Template">
<div>--------------</div>
</div>

To make clear what is going on first comment out the call to processAll in app.onactivate in the generated default.js file. If you recall what happens is that processAll scans the HTML for tags with data-win-control attributes and then replaces them with controls of its own construction.

If you run the program after commenting out processAll you will see a single line of dashes at the location of the Template div - after all why would you see anything else?!

 

dash0

 

To make the Template do its magic we have to invoke the JavaScript code that scans the DOM and implements the Template Object in JavaScript. All we have to do is call the usual processAll function to convert elements with data-win-control attributes into controls. To do this simply uncomment the processAll call or add a call to it in a routine that is activated after the DOM has been loaded.

If you now run the program you will discover that the contents of the Template element have gone missing i.e.you now can't see the dashed line.

 

blank

 

This is general behaviour Templates hide their contents when converted into custom controls.

A useful template

The next step is to do something useful with our Template.The key idea here is that the Template object has a render method which instantiates the contents of the Template as a DOM sub-tree. What you do with this sub-tree it up to you but in many cases you will simply add it to the main DOM tree of the page you are creating.

So for example to create an instance of the content of our Template, i.e. a single <div> with a dashed line for its text node all we have to do is call the Templates render function - but there is a complication.

As is the way with most WinRT methods it does not return the result but a Promise object. The reason is that in principle rendering a template could take a long time and so the render method is implemented as an asynchronous call and so returns a Promise object.

There are many things to say about Promise objects but for the moment the only thing we need to know is that you can use the promise.then() method to call a function when the task is  completes successfully  and an optional second function to be called if it fails.

So the entire process of rendering the template is:

template.render().then(function(element){
...
});

and the rendered DOM subtree is returned as the element parameter  and we can write some code to work with it.

So now we have a rendered Template what do we do with it?

In most cases the answer is that we add it to some existing element in the HTML. For example if we add a div with id Display:

<div id="Display">
</div>

and now after the render method completes we can simply add the result to the DOM within the div:

Display.appendChild(element);

Remember that any id you specify within an HTML tag is converted to a global variable which references the corresponding DOM object.

The entire HTML is:

<body>
<div id="Mytemplate"
data-win-control="WinJS.Binding.Template">
<div>--------------</div>
</div>
<div id="Display">
</div>
</body>

and the JavaScript is:

WinJS.UI.processAll();

var template = Mytemplate.winControl;
template.render().then(
function (element) {
Display.appendChild(element);
});

Now if you run the program you will once again see a dashed line:

dash1

 

So we have gone from a dashed line created by standard HTML to a dashed line created by rendering a template.