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

 

 


2 Trackbacks

  1. By Dew Drop – September 26, 2013 (#1,632) | Morning Dew on September 26, 2013 at 1:02 pm

    [...] Special syntax for data-win-options strings with WinJS controls (Kraig Brockschmidt) [...]

  2. [...] Special syntax for data-win-options strings with WinJS controls (Kraig Brockschmidt) [...]