WinRT JavaScript - Templates & Data Binding
Written by Mike James   
Wednesday, 18 January 2012
Article Index
WinRT JavaScript - Templates & Data Binding
Templates and data
Data binding

 

So what is the point?

We started with a dashed line within the Template <div> tags. We created the Template object and its content was hidden i.e. no dashed line. Now we render the Template and add the result back and we have a dashed line again.

The point is that we can now render the Template as many times as we like. For example if we render the Template a second time:

document.addEventListener(
"DOMContentLoaded", function (e) {
WinJS.UI.processAll();

var template = WinJS.UI.getControl(
document.getElementById("Mytemplate"));

template.render().then(function(element){
var display=
document.getElementById("Display");
display.appendChild(element);
});
 template.render().then(function(element){
var display=
document.getElementById("Display");
display.appendChild(element);
});
});

Then the result is two dashed lines.

 

dash2

 

Ok if you are not impressed by two dashed lines keep in mind that the contents of a Template can be anything you care to make it.

The outer container

There is one subtly that I haven't mentioned. When the Template is rendered it is returned within a <div> container. The reason for this is that it is easier to add the DOM objects being created to some outer container and it has a class= "win-template"  attribute so that the rendered Template can be styled.

In most cases the fact that the outer container is a div makes no difference. Occasionally, however you might want it to be something else and you can specify the outer container as the second parameter in the render method - the use of the first parameter is discussed later.

For example, to put the rendered Template into a <span> container you would use something like:

var container = 
document.createElement("span");
template.render(null,container).
then(function (element) {

The overall result is the same but now the rendered DOM objects would be contained within an outer span element.

An imperfect example

At this point it is time to give a slightly more convincing example. Lets use a template to construct a table. In a perfect world the template would be a single table row of table data Something like

<div id="Mytemplate" data-win-control= 
"WinJS.Binding.Template">  
      <td>One</td>
      <td>Two</td>
      <td>Three</td>
      <td>Four</td>
</div>

The idea begin that you would render these <td> elements into a table row <tr> container and then add it to a table <table> element. This doesn't work because the <td> tags don't render. The reason is that <td> tags don't make much sense outside of a <table>. and render simply returns the text contained within each as a single string. This could be a temporary situation and later version of the Template object will be able to render table rows.

After trying various work arounds the simplest solution to the problem is to render a table with a single row and then use DOM object manipulation to extract the row and add it to another table. This isn't ideal but it works. The HTML is for the template is:

<div id="Mytemplate" data-win-control=
"WinJS.Binding.Template">
<table>
     <tr>
      <td>One</td>
      <td>Two</td>
      <td>Three</td>
      <td>Four</td>
    </tr>
   </table>
</div>

We also need a table to accept the result of rendering the Template:

<table id="Display" border="1">
</table>

The JavaScript is easy but it helps to know exactly what the render method returns as a DOM object:

<table>
<tbody>
<tr>
<td>One</td>
<td>Two</td>
<td>Three</td>
<td>Four</td>
</tr>
</tbody>
</table>

You also need to remember that by default this is rendered into a div element. So

element.firstElementChild

Is the <table> element. Using firstElementChild again gives the <tbody> element and once more gives the <tr> element which is what we want.

So the render method is:

template.render().then(
function (element) {
var display =
document.getElementById("Display");       
var tr = element.firstElementChild.
firstElementChild.firstElementChild;
display.appendChild(tr);
});

This may not be an elegant way to get the table row but it works and illustrates the point.



Last Updated ( Wednesday, 18 January 2012 )