[Update: added note that you can specify array and object literals and made slight correction that the control usually calls setOptions, not the parser.]

When declaring a WinJS control in HTML, you specify the control’s constructor in the data-win-control attribute for the host element (typically a <div> but not always), and specify options in the data-win-options attribute. When the control is instantiated through WinJS.UI.process or processAll, WinJS will parse the data-win-options string and pass it to a control’s constructor (which then often calls WinJS.UI.setOptions with the object). This makes a simple way to configure the control declaratively rather than writing JavaScript to do the same thing.

The documentation for data-win-options is pretty basic. It pretty much says that each entry in the string is of the form <property>: <value> with multiple entries separated by commas. This is what we see most often, for instance:

<button data-win-control=”WinJS.UI.AppBarCommand” data-win-options=”{id: ‘accept’, label: ‘Accept’, icon: ‘accept’}”></button>
<div class=”section1″ data-win-control=”WinJS.UI.HubSection” data-win-options=”{header: ‘Images’, isHeaderStatic: true}”>
<div class=”differentRatingColor” data-win-control=”WinJS.UI.Rating” data-win-options=”{averageRating: 3.4, userRating: 4}”>

What we see here are basically just literal values like 4 (integer), 3.4 (float), true (Boolean), and ‘accept’ (string), which are the most common. However, there are other possibilities for values, many of which you can find if you grep the SDK JavaScript samples for “data-win-options”. To summarize:

  • Values can dereference objects, namespaces, and arrays using dot notation or brackets ([ ]’s), or both. [ ] notation supports the use of array literals.
  • Values can be objects surrounded by { }, which is how you assign values to complex properties. Object literals are supported here.
  • Values can be an id of another element in the DOM, provided that the element has an id attribute and is declared earlier in the markup so it’s available when the present control is instantiated.
  • Values can use the syntax select(‘<selector>’) to declaratively reference an element in the DOM (assuming again that it’s already created)

Here are some examples.

Dot notation to reference members of an enumeration or namespace; the latter is common with a ListView control where the data model has a namespace or a namespace with event handlers for app bar commands:

data-win-options=”{ selectionMode: WinJS.UI.SelectionMode.multi, tapBehavior: WinJS.UI.TapBehavior.toggleSelect }”
data-win-options=”{ itemDataSource: DefaultData.bindingList.dataSource }”
data-win-options=”{id: ‘tenDay’, label: ‘Ten day’, icon: ‘calendarweek’, type: ‘toggle’, onclick: FluidAppLayout.transitionPivot }”

Dot notation plus array dereferences (see the Adaptive layout with CSS sample in html/app.html):

data-win-options=”{ uri: ‘/html/current.html’, data: FluidAppLayout.Data.mountains[0].weatherData[0] }”
data-win-options=”{ uri: ‘/html/tenDay.html’, data: FluidAppLayout.Data.mountains[0].weatherData }”

Object notation (commonly used with ListViews to specify its layout object, also showing some dot notation):

data-win-options=”{ layout: {type: WinJS.UI.GridLayout} }”
data-win-options=”{ selectionMode: ‘none’, tapBehavior: ‘none’, swipeBehavior: ‘none’, layout: { type: WinJS.UI.GridLayout, maxRows: 2 } }
data-win-options=”{ itemDataSource: Data.list.dataSource, layout: {type: SDKSample.Scenario1.StatusLayout} }

To declaratively refer to an existing element in the DOM, you have two choices.First is to use the id of the element, that is, the same name that is in that element’s id attribute. Note that you do not make that name a string literal, but specify it directly as an identifier. For example, if somewhere earlier in markup we declare a binding template:

<div id=”smallListItemTemplate” data-win-control=”WinJS.Binding.Template”><!– … –></div>

then we can reference that control’s root element in an options string as follows:

data-win-options = “{ itemTemplate: smallListItemTemplate }”

This works because the app host automatically creates variables in the global namespace for elements with id attributes, and thus the value we’re using is that variable.

The other way is using the select syntax, which is a way of inserting the equivalent of document.querySelector into the options string (technically WinJS.UI.scopedSelect, which calls querySelector). So the previous options string could also be written like this:

data-win-options = “{ itemTemplate: select(‘smallListItemTemplate’) }”

Alternately, if we declared a template with a class instead of an id:

<div class=”templateSmall” data-win-control=”WinJS.Binding.Template”><!– … –></div>

then we can refer to it as follows:

data-win-options = “{ itemTemplate: select(‘templateSmall’) }”

The HTML AppBar control sample in html/custom-content.html and the HTML flyout control sample in html/appbar-flyout.html):

data-win-options=”{ id: ‘list’, type: ‘content’, section: ‘selection’, firstElementFocus:select(‘.dessertType’), lastElementFocus:select(‘.dessertType’) }”
data-win-options=”{ id:’respondButton’,label:’Respond’,icon:’edit’,type:’flyout’,flyout:select(‘#respondFlyout’) }”

The HTML Repeater control sample also uses select to assign a template to the control:

data-win-options=”{ data: Data.samples2, template: select(‘.template’) }

At present, select is the only method that you can use in this way.

 


Continuing from Part 1, to implement an binding initializer function directly looks like this, which is taken from scenario 1 of the Declarative binding sample (for 8.1):

var toCssColor = WinJS.Binding.initializer(
function toCssColor(source, sourceProperty, dest, destProperty) {
function setBackColor() {
dest.style.backgroundColor =
rgb(source.color.red, source.color.green, source.color.blue);
}

        return WinJS.Binding.bind(source, {
color: { red: setBackColor, green: setBackColor, blue: setBackColor, }
});
}
);

// A little helper function to convert from separate rgb values to a css color
function rgb(r, g, b) { return “rgb(” + [r, g, b].join(“,”) + “)”; }

WinJS.Namespace.define(“BasicBinding”, {
toCssColor: toCssColor
});

WinJS.Binding.initializer is just an alias for WinJS.Utilities.markSupportedForProcessing, which It makes sure you can reference this initializer from processAll and doesn’t add anything else where binding is concerned.

The arguments passed to your initializer clearly tell you which properties of source and target (dest) are involved in this particular relationship. The source argument is the same as the dataContext given to processAll, and dest is the element on which this particular initializer was declared (which can be anywhere below the rootElement given to processAll). The sourceProperty and destProperty arguments are both arrays that contain the “paths” to their respective properties, where each part of the identifier is an element in the array. That is, if you have an identifier like style.color in data-win-bind, the path array will be [style, color].

With all this information in hand, you can then set up whatever binding relationships you want by calling the source’s bind method with whatever properties and handlers you require. Note that although sourceProperty is what’s present in the data-win-bind attribute, you’re free to wire up to any other property you want to include in the relationship. The code above, for example, will be called with sourceProperty equal to [color], but it doesn’t actually bind to that directly. It instead uses a binding descriptor with WinJS.Binding.bind to hook up the setBackColor handler to three separate color subproperties. Although setBackColor is used for all three, you could just as easily have separate handlers for each one if, for example, each required a unique conversion.

Ultimately, what’s important is that the handler given to the source.bind method performs an appropriate update on the target object. In the code above, you can see that setBackColor sets dest.style.backgroundColor.

Hmmm. Do you see a problem there? In the Declarative binding sample, try changing the last data-win-bind attribute in html/1_BasicBinding.html to set the text color instead:

data-win-bind=”style.color : color BasicBinding.toCssColor”

Oops! It still changes the background color! This is because the initializer isn’t honoring destProperty, and that would be a difficult bug to track down when it didn’t work as expected. Indeed, because the initializer pays no attention to destProperty you use a non-existent identifier and it will still change the background color:

data-win-bind=”some.ridiculous.identifier : color BasicBinding.toCssColor”

Technically speaking, then, we could rewrite the code as follows:

dest.[destProperty[0]].[destProperty[1]] = rgb(source.color.red, source.color.green, source.color.blue);

Even this code makes the assumption that the target path has only two components—to be really proper about it, you need to iterate through the array and traverse each step of the path. Here’s a way to do that:

var target = “dest”;
for (var i = 0, len = destProperty.length – 1; i < len; i++) {
target += “.” + destProperty[i];
}

target = eval(target);
var lastProp = destProperty[i];

function setBackColor() {
target[lastProp] = rgb(source.color.red, source.color.green, source.color.blue);
}

Note that I’m building that reference outside of the setBackColor handler because there’s no need to rebuild it every time a source property changes.

Remember also that sourceProperty can also contain multiple parts, so you may need to evaluate that path as well. The sample gets away with ignoring sourceProperty because it knows it’s only using the toCssColor initializer with source.color to begin with. Still, if you’re going to write an initializer, best to make it as robust as you can!

 

[7/23/13: Corrected one statement above on the source and dest arguments to the initializer. It has incorrectly stated that dest was the same as the rootElement to processAll; it’s the element where the initializer is declared.]


I’ve been writing about this subject more thoroughly for the second edition of my book (view preview here), and thought to share the results here in two parts.

When WinJS.Binding.processAll encounters a data-win-bind attribute on an element, its main job is to take each <target property> : <source property> [] string and turn it into a real binding relationship. Assuming that the data source is observable, this basically means calling the source’s bind method with the source property name and some handler that will update the target property accordingly.
The purpose of the initializer function in this process is to define exactly what happens in that handler, that is, what happens to the target property in response to a source property update. In essence, an initializer provides the body of the handler given to the source’s bind (that is, each binding source is an object that has a bind method, typically brought in from the WinJS.Binding.mixin or observableMixin, which is done when you call WinJS.Binding.as or WinJS.Binding.define for a data source).

In a simple binding relationship, that code might simply copy the source value to the target, or might involve a converter function. It could also consolidate multiple source properties—you can really do anything you want here. The key thing to remember is that the initializer itself will be called once and only once for each binding relationship, but the code it provides, such as a converter function, will be called every time the source property changes.

Now if you don’t specify a custom initializer within data-win-bind, WinJS will always use a default, namely WinJS.Binding.defaultBind.  It simply sets up a binding relationship that copies the source property’s value straight over to the target property, as you’d expect. In short, the following two binding declarations have identical behavior:

data-win-bind=”innerText: name”
data-win-bind=”innerText: name defaultBind”

WinJS.Binding provides a number of other built-in initializers that can come in handy:

  • oneTime Performs a one-time copy of the source property to the target property without setting up any other binding relationship. This is necessary when the source is a WinRT object, as the proxy used for marshalling doesn’t supporting observability for one-way or two-way binding.
  • setAttribute and setAttributeOneTime Similar to defaultBind and oneTime but injects a call to the target element’s setAttribute method instead of just copying the source value to a target property. This is how you bind to DOM element attributes rather than object properties.
  • addClassOneTime (WinJS 2.0 only) Like setAttributeOneTime except that it interprets the source property as a class name and thus calls the target element’s classList.add method to apply that class. This is useful when working with binding templates.

Beyond these, we enter into the realm of custom initializers. The most common and simplest case is when you need to inject a converter into the binding relationship. All this takes on your part is to pass your conversion function to WinJS.Binding.converter, which returns the appropriate initializer (that’s also marked for declarative processing). For example, in the example below the function userTypeToColor is a simple data-conversion function, so we can create an initializer within the MyInitializers namespace as follows:

WinJS.Namespace.define(“MyInitializers”, {
//…
typeColorInitializer: WinJS.Binding.converter(userTypeToColor)
});

which we use in the HTML like so:

<span id=”loginName3″
data-win-bind=”innerText: name; style.color: userType MyInitializers.typeColorInitializer”>
</span>

Doing anything more requires that you implement the initializer function directly. We’ll pick up this subject in Part 2.



As one who works in HTML/JS most of the time, it’s exciting to see a number of new WinJS controls and some improvements to existing ones, namely the ListView and the AppBar.

New controls can be found when you scan the WinJS.UI namespace in the updated documentation:

  • BackButton: a cleaner back button implementation that hooks directly into WinJS.Navigation APIs. Previously, most of this functionality was provided through the Visual Studio templates, where a standard <button> was just styled to look like a back button, and the PageControlNavigator code handled the details like calling WinJS.Navigation and handling keyboard events. The BackButton does such things in a more encapsulated way. Refer to the Navigation and navigation history sample.
  • Hub: a significant new control for implementing app home pages with a hub design. In Windows 8, developers had to do this manually, or use a third-party library (Telerik created a hub control, for instance). So now we have a standard implementation. Refer to the HTML Hub Control sample.
  • ItemContainer/Repeater: Together, these provide for a lightweight list implementation, namely where you just need to create a repeating, templated display of data items and don’t need all the interactivity of a ListView. Refer to the HTML ItemContainer sample and the HTML Repeater control sample.
  • NavBar: a standard implementation of a top app bar as used for navigation. Refer to the HTML NavBar Control sample.
  • SearchBox: with in-app search moving to the app canvas instead of the search charm, WinJS adds a control that provides the same kind of search contract interactivity with the app that the charm did. Refer to the SearchBox control sample.

Where the ListView is concerned, many things have changed. I haven’t had a chance to get into the details yet, but one thing I know is that doing a custom layout is much simpler as the whole layout model has changed from a complex custom interface to one based primarily on CSS (called ILayout2). Custom layouts were possible before, but very difficult to implement and it never really got documented–so now they’re easier. For more, see the HTML ListView custom layout sample. Note that we also have some new WinJS layouts, such as CellSpanningLayout, an Orientation option to make the GridLayout (pan vertically), options to add group headers to the ListLayout. There is also drag-and-drop reordering support now–see the HTML ListView reorder and drag and drop sample.

For more details and demonstrations (as well as bits on the AppBar), see Paul Gusmorino’s What’s New in WinJS talk from //build 2013.

 


One of the next most interesting APIs added to Windows 8.1 that I also write in Chapter 4 of my Second Edition Preview is the Windows.Web.Http.HttpClient API (and associated classes). On the surface–and the API is designed to be very simple and easy to use for common cases–it seems redundant with other available APIs like WinJS.xhr (i.e. XMLHttpRequest) or the HttpClient API in .NET. In that sense it at least provides a robust HTTP API for C++ developers.

Digging down a little deeper, however, this new API goes well beyond the existing ones and should, in time, obsolete the other methods. For one thing, it provides cache control and access to cookies unlike the existing APIs. In comparison to the .NET API, this new WinRT API works with the WinINet cache, so benefits from any caching that happens via Internet Explorer, other apps, or the pre-caching API that’s now in Windows.Networking.BackgroundTransfer.ContentPrefetcher class.

The new API also provides a low-level hooking mechanism called filters that allows you to place handling code beneath the level of app logic. The HttpClient sample that’s now available shows how to create filters for authentication, 503 retries, and network cost awareness, meaning that the rest of the app can ignore the details of such concerns. That is, instead of having every HTTP request in your app have to think about cost awareness, you let the filter do that. The rest of the code either just gets the data or doesn’t, which makes it a lot simpler to write.

For additional details, also see Peter Smith’s talk from //build 2013: Five Great Reasons to Use the New HttpClient API to Connect to Web Services.


One of the most important features in Windows 8.1 Preview for HTML/JS developers is the x-ms-webview element that’s added to HTML. If you’ve never developed in XAML before, the webview is a control that renders arbitrary HTML, CSS, and JavaScript, and allows for the app to invoke script within the webview and the webview to raise events to the app. Yes, you could do some of this with the iframe element in Windows 8, of course, but the iframe had a number of limitations. For example, if the site you wanted to host contained frame-busting code, you were simply out of luck. HTML/JS apps also lacked a way to load up downloaded or locally-generated HTML/CSS/JS into an iframe. It’s also not possible to render an iframe to a bitmap.

Fortunately, you can do all this with the webview, as well as hook into an app-provided link resolver for cases where references within the HTML need to be patched up at runtime (as when referenced images aren’t directly on the file system).

I’ll let you learn more about the webview yourself. I already wrote a bunch about it in the first preview of Programming Windows Store Apps with HTML, CSS, and JavaScript, Second Edition, specifically Chapter 4.

You can also learn more from John Hazen’s talk at //build 2013 which we just presented last week: Webview: bringing the web to your app.




Wrapping up this series from part 3 we have two members of the WinJS.UI namespace that match others in WinJS.Utilites for obscurity.

The first is WinJS.UI.scopedSelect, to which you provide a CSS selector and an element. This function is documented as “Walks the DOM tree from the given element to the root of the document. Whenever a selector scope is encountered, this method performs a lookup within that scope for the specified selector string. The first matching element is returned.” What’s referred to here as a “selector scope” is a property called msParentSelectorScope, which WinJS sets on child elements of a fragment, page control, or binding template. In this way, you can do a querySelector within the scope of a page control, fragment, or template without having to start at the document level. The fact that it keeps going up toward the document root means that it will work with nested page controls or templates.

The other is WinJS.UI.getItemsFromRanges, which takes a WinJS.Binding.List and an array of ISelectionRange objects (with firstIndex and lastIndex properties). It then returns a promise whose results are an array of items in that data source for those ranges. Simply said, this exists to translate multiple selections in something like a ListView control into a flat array of selected items–and, in fact, is what’s used to implement the getItems method of a ListView’s selection property. So if you implement a list control of your own around a WinJS.Binding.List, you can use getItemsFromRanges to do the same. The method is provided, in other words, to work with the data source as that it a separate concern from the ListView itself.