April 28, 2015 // By Caleb McElrath
The previous Magenic Blog post I wrote, “Introducing HTML & JS Data Templates for Metro Apps,” introduced data templates for Windows Store applications. This is a follow up article that will dive deeper with nested data templates where data templates will have data templates! Please read the introductory post if you are unfamiliar with data templates in Windows Store apps.
In the following sections, each topic will be described along with code snippets and screen captures of the resultant display. For a more interactive experience, please download the usable solution available at the end of this article. This solution contains a functional version of the code snippets provided. Please note, the solution will only work in a Windows 8 development environment.
Nested Data Templates
Like basic templates, there are four necessary components when working with nested templates: Template, Data Source, Binding, and Render Target. Building off basic templates, nested templates provide further flexibility by adding more levels of control over the presentation of data. Using the methods described here will allow the potential for indefinite levels of nesting. This greatly increases the flexibility of data presentation. Please note that this article will only go as far as a single nested template.
The sample that will be worked through will use nested templates for multiple data objects. Each of the four components of data templates will be described beginning with the markup.
The Markup
The markup defines the data templates and render targets. Below is the markup used:
<div id="template" data-win-control="WinJS.Binding.Template"> <div> <h3 data-win-bind="innerText: type;"></h3> <div id="innerTarget"></div> <div id="innerTemplate" data-win-control="WinJS.Binding.Template"> <em data-win-bind="innerText: details;"></em> </div> </div> </div> <div data-role="main"> <h2>Nested Templates</h2> <div id="target"></div> </div>
The markup above includes two data templates and two render targets. First, an outer template is created as a WinJS.Binding.Template control. This contains a heading bound to the ‘type’ property of the data source item (which will be described in the next section). Then a div element is defined with an id of ‘innerTarget’. This will be used as the render target for the inner data template. This template is defined immediately following the inner render target as another WinJS.Binding.Template control. Finally, the inner template contains an element bound to the ‘details’ property of the data source item.
Now that the templates are defined, it must be placed inside the DOM. Cue the final render target.
... <div id="target"></div> ...
This render target is simply a div element with the id of ‘target’ for easy referencing in JavaScript. This will contain the filled templates.
The Data Source
This scenario needs multiple data objects. The snippet below uses a new WinJS.Binding.List to represent a few of Magenic’s “Portfolio” items as they were at the time of this writing.
var portfolio = new WinJS.Binding.List( [ {type:"Case Studies", details:"Payment Solution Organization" }, {type:"White Papers", details:"SQL 2012: Bringing \"Big Data\" to the Desktop" }, {type:"Videos", details:"Choosing a Development Partner" } ] ); WinJS.Namespace.define( "Data", { Portfolio: portfolio, } );
A bindable portfolio object is created with the given collection of data objects as its items. A namespace is then created to provide access to the object in the form of Data.Portfolio.
The Template, Data Source, and Render Targets have been created. The last component is the binding mechanism. The next section will explore, in detail, the necessary code needed to complete this data-binding scenario.
The Binding
There are many ways to set up data-binding. This particular case uses the WinJS.UI.process method along with various helper methods and properties which will be explained in more detail below. First, let’s see the JavaScript:
var outerTemplate = document.querySelector( "#template" ); var outerTarget = document.querySelector( "#target" ); WinJS.UI.process( outerTemplate ).then( function ( outerControl ) { var innerTemplate = outerControl.element.querySelector( "#innerTemplate" ); var innerTarget = outerControl.element.querySelector( "#innerTarget" ); WinJS.UI.process( innerTemplate ).then( function ( innerControl ) { for ( var i = Data.Portfolio.length - 1; i >= 0; i-- ) { var data = Data.Portfolio.getItem( i ).data; WinJS.Utilities.empty( innerTarget ); innerControl.render( data, innerTarget ); outerControl.render( data, outerTarget ); } } ); } );
The basic process for data binding is used but with a few modifications to support nested templates. To begin the binding process, the outer template and outer target are obtained as seen below.
var outerTemplate = document.querySelector( "#template" ); var outerTarget = document.querySelector( "#target" );
Here, the document object’s querySelector method is used passing in the id of the template and target. Next, the WinJS.UI.process method is called passing in the outer template.
WinJS.UI.process( outerTemplate ).then( function ( outerControl ) { ... - See more at: http
As described in the introductory post, the process method returns a Promise object. This Promise object’s ‘then’ method is called where further processing of the templates occurs. The ‘then’ method takes a function which accepts a parameter. This parameter is the outer template control. Within this function, the inner template and inner target are obtained.
var innerTemplate = outerControl.element.querySelector( "#innerTemplate" ); var innerTarget = outerControl.element.querySelector( "#innerTa
The same mechanism is used to retrieve references to the inner template and inner target as was used for the outer template and outer target. Then, the WinJS.UI.process method is called again, this time passing in the inner template.
WinJS.UI.process( innerTemplate ).then( function ( innerControl
The resultant Promise object’s ‘then’ method is used taking a function whose parameter is the inner template control. Within this function, the data source’s items are iterated.
for ( var i = Data.Portfolio.length - 1; i >= 0; i-- ) { var data = Data.Portfolio.getItem( i ).data; WinJS.Utilities.empty( innerTarget ); innerControl.render( data, innerTarget ); outerControl.render( data, outerTarget ); }
For every iteration, four actions take place. The first action is to obtain the data item through the ‘getItem’ method of the data source. This method returns an object containing the ‘data’ property. This property is where the actual data is stored for each data item. Next the inner target is cleared using the WinJS.Utilities.empty method. More information on the empty method can be found on MSDN: “WinJS.Utilities.empty function”. This method removes all of the child nodes from the specified element. It is necessary to clear the inner target to ensure no remnants exist of previous iterations. The remaining two actions render the data item. First the innerControl’s render method is called passing in the data item and the inner target. The inner content is now complete and the outer target is ready for its rendering. To do this, the outerControl’s render method is called passing in the data item and the outer target.
The iterations continue processing the data source until there are no more items in the data source to process.
The Outcome
The four components of data templates are complete. Running the app would produce results similar to the screen capture in Figure 1 depending on your choice of styling. Using nested templates in this way allows for more flexible, data-driven Windows Store Apps.

Figure 1 – Styled outcome of using a nested template
Conclusion
Nested templates are a great way to enhance the flexibility of an app’s user interface. The real benefit to this is shown when using separate data sources for inner and outer templates. Imagine a web service API for news articles that include separate calls for headlines and the full article content for each headline. The outer template would contain the headline data while the inner template would contain the article content. Using nested templates in this way provides a unified template design keeping the maintainability that comes with using data templates.