Devhammer's Den


Apr 26, 2012

Databinding in Windows 8 JavaScript Metro style Apps

[ NOTE: This post was written using the Visual Studio 11 beta and Windows 8 Consumer Preview…as with any pre-release software, the code and concepts are subject to change in future versions ]

One of the nice features of the new JavaScript Windows Metro style app templates in the Visual Studio 11 beta is that they provide built-in support for databinding, using sample data in a JSON array. Folks who have experience in the XAML world may not see this as a particularly big deal, since Silverlight and WPF have supported databinding for a long time.

For web applications, however, data binding is still a concept that's evolving. While there are third-party libraries like Knockout.js that provide client-side databinding (and my fellow DE David Isbitski recently published a blog post detailing how you can use Knockout in a Metro style app, if that's your cup of tea), but in general the web world is a little behind the curve compared to XAML-based databinding.

Back to Windows 8, both the Grid Application template and the Split Application template include markup and code that demonstrates databinding to sample data contained in a file called data.js (in the js folder off the root of the app). The data.js file contains static sample data stored as JSON arrays, along with some helper functions that expose (via WinJS.Namespace.define) the collections of items, groups, and items from a specified group. This data is used by the binding templates in the HTML markup included in the application templates, such as itemsPage.html in the Split Application template.

As with most generated JavaScript files in the Metro style app templates, data.js uses a self-executing anonymous function to wrap the code that defines the sample data. This both ensures that the code that creates the JSON data (and related helper code) executes as soon as data.js is loaded, and also hides the internal variables declared in data.js so that they do not pollute the global JavaScript namespace.

Both application templates use the same sample data, which has the following schema:

sampleGroups
- key
- title
- subtitle
- backgroundImage (maps to one of 3 variables containing a base64 encoded png image)

sampleItems
- group (maps to sampleGroups above)
- title
- subtitle
- description (maps in the sample data to the itemDescription variable)
- content (maps in the sample data to the itemContent variable)
- backgroundImage (maps to one of 3 variables containing a base64 encoded png image)

In addition to declaring sampleGroups and sampleItems as JSON arrays, data.js creates a WinJS.Binding.List called list, and then calls its createGrouped method (passing in the parameters for grouping, which in this case are functions that return the group key and group), and finally loops through the sampleItems array using forEach, and adds each item to the binding list object.

Once the binding list(s) are available, they are typically bound to the HTML markup either declaratively with attributes or programmatically in JavaScript. For example, in the itemsPage.html file of a Split application, the default UI for displaying the groups is a ListView control, which is implemented as a div element with the data-win-control attribute set to WinJS.UI.ListView:

<div class="itemslist" aria-label="List of groups" 
    data-win-control="WinJS.UI.ListView" 
    data-win-options="{ selectionMode: 'none' }">
</div>

(note that in order for the data-win-control attribute to convert the div element into a ListView control, the app must call WinJS.UI.processAll(), which is done by default in default.js in the Grid and Split application templates)

In the case of the Split application template, the JavaScript file for itemsPage.html, which is named itemsPage.js contains the following code in the ready handler which sets the datasource of the ListView to the groups defined in the sample data:

   1:  var listView = element.querySelector(".itemslist").winControl;
   2:  ui.setOptions(listView, {
   3:      itemDataSource: data.groups.dataSource,
   4:      itemTemplate: element.querySelector(".itemtemplate"),
   5:      oniteminvoked: this.itemInvoked.bind(this),
   6:  });

(in the code above, ui is an alias to WinJS.UI)

The code above gets a reference to the ListView control by querying for the class name associated with the control, and then passes that object into the call to WinJS.UI.setOptions, setting the itemDataSource to data.groups.dataSource (which is the dataSource property on the WinJS.Binding.List object), and the itemTemplate to the item template defined in the markup (again, obtained by querying for the matching class name).

Here's what the item template looks like:

<!-- This template is used to display each item in the ListView declared below. -->
<div class="itemtemplate" data-win-control="WinJS.Binding.Template">
    <img class="item-image" src="#" data-win-bind="src: backgroundImage; alt: title" />
    <div class="item-overlay">
        <h4 class="item-title" data-win-bind="textContent: title"></h4>
        <h6 class="item-subtitle win-type-ellipsis" data-win-bind="textContent: subtitle"></h6>
    </div>
</div>

 

Notice again the use of the HTML5 data- attributes, in this case both data-win-control to define the outside div element as a WinJS.Binding.Template, and the data-win-bind attributes to define the relationship between attributes of the individual elements (for example, the src attribute of the img element) and the values to which they're being bound (in the case of the img element, the src attribute is bound to the backgroundImage property, and the alt attribute is bound to the title property).

Once the code in the ready handler has executed, the call to WinJS.UI.processAll() from default.js will complete the binding process, and you should see something like the following:

SplitApp

Databinding in JavaScript Windows Metro style apps is easy and straightforward, and having a template that provides a clear implementation with sample data can help you get started with your own application. This post just scratches the surface, but I wanted to walk through the basics of the databinding implementation before delving deeper into topics like customization and binding converters, which I'll cover in future posts.

If you just can't wait, here's a list of additional resources that will help you dig deeper into databinding in JavaScript Metro style apps:

Tags: Windows 8, Metro, JavaScript, HTML5

Comments powered by Disqus

Visitors

Disclaimer

The views expressed on this weblog are mine and do not necessarily reflect the views of my employer.
All postings are provided "AS IS" with no warranties, and confer no rights.

Unless otherwise noted, all code provided in this blog is copyright © G. Andrew Duthie, and licensed under the Microsoft Limited Public License (Ms-LPL). All rights reserved.



worldmaps