How to use templates to bind data (HTML)
[ This article is for Windows 8.x and Windows Phone 8.x developers writing Windows Runtime apps. If you’re developing for Windows 10, see the latest documentation ]
Windows Library for JavaScript templates are a convenient way to format and display multiple instances of data. You can use these templates in conjunction with ListView and FlipView objects to specify the way you want them to be displayed. You can also use a template to bind multiple instances of a data object without using a predefined view. For more information about using a template with a ListView, see Quickstart: Add a ListView. For more information about using a template with a FlipView, see Adding FlipView controls. The following procedure shows how to use a template with an array.
You can define a template declaratively as a WinJS control and specify its internal structure and style. Even though they are declared as DIV elements, templates are not processed as part of the DOM and are not returned as part of DOM search results. You can either specify the DIV element in which the template should appear, or allow the render method to create its own DIV element. This topic shows how to use a template to bind a variable number of bindable data objects to a DIV element. The user chooses the number of objects to display by selecting an item from a drop-down list.
Prerequisites
- Working through the topic Quickstart: Binding data and styles to HTML elements might help you to complete the steps in this how-to topic.
Instructions
Step 1: Setting up a project to use a template
To set up a project to use a template
Create a blank Windows app using JavaScript and name it TemplateExample.
Inside the BODY element of the default.html file, add a DIV element for the template and give it an ID of templateDiv, and then add a data-win-control attribute that has a value of "WinJS.Binding.Template", as shown here.
<body> <div id="templateDiv" data-win-control="WinJS.Binding.Template"></div> </body>
We'll return to add the internal structure of the template after we've defined the data object.
Step 2: Defining a data object and binding it to the fields of the template
Inside the immediately-invoked function in default.js, declare an object that contains several fields. In this case, we'll use WinJS.Binding.define, which makes all the properties bindable.
(function () { "use strict"; // Other app code ... // Define a Person object with bindable properties. var Person = WinJS.Binding.define({ name: "", color: "", birthday: "", petname: "", dessert: "" }); })();
To display the fields of this object in the template, you need a list whose items correspond to the fields of the data object, as shown here. Add the following code inside the BODY tags in default.html.
<div id="templateDiv" data-win-control="WinJS.Binding.Template"> <div class="templateItem" data-win-bind="style.background: color"> <ol> <li><span>Name :</span><span data-win-bind="textContent: name"></span></li> <li><span>Birthday:</span><span data-win-bind="textContent: birthday"></span></li> <li><span>Pet's name: </span><span data-win-bind="textContent: petname"></span></li> <li><span>Dessert: </span><span data-win-bind="textContent: dessert"></span></li> </ol> </div> </div>
Below the template code in default.html, add a DIV element where the template should be rendered.
<div id="templateControlRenderTarget"></div>
Step 3: Controlling the number of objects displayed
For the purposes of this example, we'll instantiate three Person objects and add a drop-down list so the user can select the number of Person objects to display.
Inside the BODY tags in default.html, add the following code.
<fieldset id="templateControlObject"> <legend>Pick a name:</legend> <select id="templateControlObjectSelector"> <option value="0">Show one</option> <option value="1">Show two</option> <option value="2">Show three</option> </select> </fieldset>
Inside the immediate-invoked anonymous function in default.js, create an array of three
Person
objects.(function () { "use strict"; // Other app code ... // Define a Person 'class' with bindable properties. var Person = WinJS.Binding.define({ name: "", color: "", birthday: "", petname: "", dessert: "" }); // Declare an array of People objects. var people = [ new Person({name:"Bob", color:"red", birthday:"2/2/2002", petname:"Spot", dessert:"chocolate cake"}), new Person({name:"Sally", color:"green", birthday:"3/3/2003", petname:"Xena", dessert:"cherry pie"}), new Person({name:"Fred", color:"blue", birthday:"2/2/2002", petname:"Pablo", dessert:"ice cream"}), ]; })();
Now add a listener to the change event of the drop-down selector. Add this code inside the handler for the app.onactivated event in default.js.
app.onactivated = function (args) { // Other activation code ... var selector = document.querySelector("#templateControlObjectSelector"); selector.addEventListener("change", handleChange, false); }
In the change event handler, select the DIV element that contains the template and the DIV element that specifies where to display the data, and then call render on the template control (which you can get from the wincontrol property of the templateDiv element). When you call render on the template, the relevant fields of the data object are bound to the template's list items.
function handleChange(evt) {
var templateElement = document.querySelector("#templateDiv");
var renderElement = document.querySelector("#templateControlRenderTarget");
renderElement.innerHTML = "";
var selected = evt.target.selectedIndex;
var templateControl = templateElement.winControl;
while (selected >= 0) {
templateElement.winControl.render(people[selected--], renderElement);
}
}
Now you can build and debug the app. When you make a selection in the drop-down list, the app displays the appropriate number of data objects.
Step 4: Allowing render to add a DIV
You do not have to give the render function a DIV you have created; render creates a new DIV if no DIV is specified. You must, however, add the new DIV to the DOM. Note that the return value of render is a WinJS.Promise. (For more information about promises, see Quickstart: using promises.) In the promise's done method you add a function that adds the new DIV.
Change the while block of the previous step as follows.
while (selected >= 0) {
templateElement.winControl.render(people[selected--])
.done(function (result) {
renderElement.appendChild(result);
});
}
Remarks
Here is the complete listing of the code in this topic.
default.html (Windows)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>TemplateExample</title>
<!-- WinJS references -->
<link href="//Microsoft.WinJS.2.0/css/ui-dark.css" rel="stylesheet" />
<script src="//Microsoft.WinJS.2.0/js/base.js"></script>
<script src="//Microsoft.WinJS.2.0/js/ui.js"></script>
<!-- TemplateExample references -->
<link href="/css/default.css" rel="stylesheet" />
<script src="/js/default.js"></script>
</head>
<body>
<div id="templateDiv" data-win-control="WinJS.Binding.Template">
<div class="templateItem" data-win-bind="style.background: color">
<ol>
<li>Name: <span data-win-bind="textContent: name"></span></li>
<li>Birthday: <span data-win-bind="textContent: birthday"></span></li>
<li>Pet's name: <span data-win-bind="textContent: petname"></span></li>
<li>Dessert: <span data-win-bind="textContent: dessert"></span></li>
</ol>
</div>
</div>
<div id="templateControlRenderTarget"></div>
<fieldset id="templateControlObject">
<legend>Pick a name:</legend>
<select id="templateControlObjectSelector">
<option value="0">Show one</option>
<option value="1">Show two</option>
<option value="2">Show three</option>
</select>
</fieldset>
</body>
</html>
default.html (Windows Phone)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>TemplateBinding</title>
<!-- WinJS references -->
<link href="/css/ui-themed.css" rel="stylesheet" />
<script src="//Microsoft.Phone.WinJS.2.1/js/base.js"></script>
<script src="//Microsoft.Phone.WinJS.2.1/js/ui.js"></script>
<!-- TemplateBinding references -->
<link href="/css/default.css" rel="stylesheet" />
<script src="/js/default.js"></script>
</head>
<body>
<div id="templateDiv" data-win-control="WinJS.Binding.Template">
<div class="templateItem" data-win-bind="style.background: color">
<ol>
<li>Name: <span data-win-bind="textContent: name"></span></li>
<li>Birthday: <span data-win-bind="textContent: birthday"></span></li>
<li>Pet's name: <span data-win-bind="textContent: petname"></span></li>
<li>Dessert: <span data-win-bind="textContent: dessert"></span></li>
</ol>
</div>
</div>
<div id="templateControlRenderTarget"></div>
<fieldset id="templateControlObject">
<legend>Pick a name:</legend>
<select id="templateControlObjectSelector">
<option value="0">Show one</option>
<option value="1">Show two</option>
<option value="2">Show three</option>
</select>
</fieldset>
</body>
</html>
default.js (Windows and Windows Phone)
(function () {
"use strict";
var app = WinJS.Application;
var activation = Windows.ApplicationModel.Activation;
app.onactivated = function (args) {
if (args.detail.kind === activation.ActivationKind.launch) {
if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
} else {
}
// Add event handler to selector.
var selector = document.querySelector("#templateControlObjectSelector");
selector.addEventListener("change", handleChange, false);
args.setPromise(WinJS.UI.processAll());
}
};
app.start();
// Define a Person 'class' with bindable properties.
var Person = WinJS.Binding.define({
name: "",
color: "",
birthday: "",
petname: "",
dessert: ""
});
// Declare an array of People objects.
var people = [
new Person({ name: "Bob", color: "red", birthday: "2/2/2002", petname: "Spot", dessert: "chocolate cake" }),
new Person({ name: "Sally", color: "green", birthday: "3/3/2003", petname: "Xena", dessert: "cherry pie" }),
new Person({ name: "Fred", color: "blue", birthday: "2/2/2002", petname: "Pablo", dessert: "ice cream" }),
];
// Update the displayed data when the selector changes.
function handleChange(evt) {
var templateElement = document.querySelector("#templateDiv");
var renderElement = document.querySelector("#templateControlRenderTarget");
renderElement.innerHTML = "";
var selected = evt.target.selectedIndex;
var templateControl = templateElement.winControl;
while (selected >= 0) {
templateElement.winControl.render(people[selected--])
.done(function (result) {
renderElement.appendChild(result);
});
}
}
})();