registering your WinJS webcomponents

In the last episode, we had a glimpse of using WinJS controls with webcomponents syntax, thanks to WinJS Contrib. Let’s dig a little deeper and see how you could use your own controls with it.

On platforms with non native implementation of webcomponents, the WinJS Contrib module is attaching an observer on each page controls (and releasing it on when disposing the page). This observer uses MutationObserver to track changes in the DOM and automatically build the WinJS controls that you registered. It means that controls, not on a page (like controls in default.html) are not instantiated. In such case, you must call « WinJSContrib.UI.WebComponents.inspect(element) » just like you would have to call WinJS.UI.processAll with vanilla WinJS.

Registering a control is just about providing the name of the DOM element, and how to map DOM attributes to your control implementation. If you don’t want to use DOM element attribute, you could still use data-win-options, or use both.

Declaring a control is quite easy. If you look in « winjscontrib.ui.webcomponents.js », you will find the declarations for WinJS controls. Lets look at the declaration for the DatePicker :

	WinJSContrib.UI.WebComponents.register('win-datepicker', WinJS.UI.DatePicker, {
		properties: ['calendar', 'datePattern', 'disabled', 'maxYear', 'minYear', 
				'monthPattern', 'yearPattern', 'onchange', 'current'],
		events : ['change']
	});	

You must call WinJSContrib.UI.WebComponents.register to wrap your control. You must at least provide the name of the DOM element, and the constructor for your control. The third argument is an object containing the mapping for your control. Within this object, the items in « properties » indicate the name of the properties that you want to map as attribute on the element, and « events » indicate the name of the events you want to map.

« properties » and « events » are shortcuts to build a mapping. You could provide a raw map if you have to do fancy stuf. Lets imagine that the calendar attribute used on DOM element must map to something like _calendarBuilder.calendar in your control. In such case you could use :

	WinJSContrib.UI.WebComponents.register('win-datepicker', WinJS.UI.DatePicker, {
		properties: ['datePattern', 'disabled', 'maxYear', 'minYear', 
				'monthPattern', 'yearPattern', 'onchange', 'current'],
		events : ['change'],
		map: {
			"CALENDAR" : {
				attribute : "calendar",
				property : "_calendarBuilder.calendar",
				type : "property",
				resolve : true
			},
			"CHANGE" : {
				attribute : "change",
				property : "_calendarBuilder.changeevent",
				type : "event",
				resolve : true
			}
		}
	});	

This syntax is more verbose but you have total control over the mapping. Note that the mapping key should be uppercase.

Another scenario that may come in mind is how do I map a fragment/page to a webcomponent ?

This is a lesser known feature of WinJS but WinJS.UI.Pages.define actually returns the constructor for the page, with the exact constructor signature of common WinJS controls (first parameters provides containing DOM element, and second parameter for control options).

To map a page/fragment to a component, you just have to pass the constructor. If you look at the searchbar control in the sample application, you will find an example that looks like this :

var SearchBarCtor = WinJS.UI.Pages.define("/controls/searchbar/searchbar.html", {
	//control implementation not mentionned here for brievity
});

//for use as standard control with data-win-control
WinJS.Namespace.define('Flickity.UI', { SearchBar: SearchBarCtor });

if (WinJSContrib.UI.WebComponents) {
   	WinJSContrib.UI.WebComponents.register('flickity-searchbar', SearchBarCtor);
}

The last use case we will cover now is for controls containing controls. Sometimes you write a control that wraps one or more other controls. You can map those controls directly to DOM attributes by using their own registration. WinJS Contrib has a control that wrap a SemanticZoom and the two associated ListView for managing list with groupings. The declaration for this control use that pattern :

WinJSContrib.UI.WebComponents.register('mcn-semanticlistviews', WinJSContrib.UI.SemanticListViews, {
	properties: [],
	controls: {
		"listview": WinJS.UI.ListView,
		"zoomedOutListview": WinJS.UI.ListView,
		"semanticZoom": WinJS.UI.SemanticZoom
	},
	map: {
		"DEFAULTGROUPLIMIT": { attribute: 'defaultGroupLimit', property: '_dataManager.defaultGroupLimit', resolve: true },
		"GROUPKIND": { attribute: 'groupKind', property: '_dataManager.groupKind', resolve: true },
		"FIELD": { attribute: 'field', property: '_dataManager.field', resolve: true },
		"ITEMS": { attribute: 'items', property: '_dataManager.items', resolve: true },
	}
});

The mapping can also have a « controls » section, which is used as a map. The key is the prefix for the control, and the value is the constructor for the control. When you register a control, the webcomponents module is creating a mapping and attach it to the constructor. That’s why you have nothing more to pass to map child control. However, the controls you are using as child map should have been declared before declaring this one.

The control can then be declared like this :

<mcn-semanticlistviews id="semanticzoom"
	listview.itemtemplate="select:#listItemTemplate"
	listview.groupheadertemplate="select:#groupItemTemplate"
	zoomedoutlistview.itemtemplate="select:#semanticItemTemplate"
	defaultGroupLimit="12"
	groupKind="global:WinJSContrib.UI.DataSources.Grouping.byField"
	field="metadata.genre"
	items="global:moviesSample">				
</mcn-semanticlistviews>

Next time we will have a look at the resolution of properties and detail the various options you have.

2 réflexions sur “registering your WinJS webcomponents

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s