[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.

 


A recent MSDN forum post asked a good question, one that I realized isn’t often adequately answered for developers new to the concept of data binding. It’s simply then question, “When do I use data binding at all?”

Here’s how I answered the question, and I’d enjoy hearing your thoughts on the matter.

Data binding is typically used to set up an automatic relationship between a data source and one or more UI elements. This is so you can

  1. Simplify the initialization of UI element contents from a data source (one-time binding)
  2. Have the UI elements update whenever the data source changes (one-way binding, which effectively includes one-time)
  3. Have changes in the UI element also be reflected back to the data source (two-data binding, which includes one-way)

When small bits of UI are involved, you can just as easily do all this manually, just by setting innerText/innerHTML values (or other attributes) within the appropriate event handler. However, when the UI gets more involved, e.g. you’re using collections or you’re starting to set up relationships to multiple properties of multiple elements, then having a more formalized structure to handle the data-to-UI wiring starts to make a lot of sense. This is really what data-binding is meant for (and really shines when you’re dealing with database sources and other large data sets.)

“Formalized structure” is what you often see referred to in the context of “view models” (e.g. model-view-controller (MVC), model-view-viewmodel (MVVM), and so forth). Those patterns are ones that have developed from data-binding capabilities; they encapsulate a structure wherein data (the model) is managed independently of how it’s shaped (view), how it’s presented (viewmodel), and how it’s manipulated procedurally (controller). These patterns achieve a ‘separation of concerns’ between data and UI, which is an adjunct to a similar but different separation between markup (HTML), styling (CSS), and code (JS).

[Here I inserted this note as the question was related to WinJS: Note that WinJS provides mechanisms for one-time and one-way data-binding, but not two-way; the latter, however, is not too hard to wire up on your own. I talk about all this in Chapter 4 of my book.]

The bottom line is that data binding is really a best practice, but not a requirement, especially in simple cases.