WinRT JavaScript - Custom Controls
Written by Ian Elliot   
Article Index
WinRT JavaScript - Custom Controls
Standard configuration
Events

Standard configuration

If this is as far as you want to go you can create and use custom controls as described so far. However our control doesn't conform to the way that other controls behave. However it is easy to add the missing functionality.

First it is usual for an element to be specified that the custom control is added to as a child - but it is possible to call the constructor without specifying an element. In this case the constructor is suppose to return the control inside a <div>. We also need to set an the standard element property on the control to the container object. We can do all this in one instruction:

this.element = element ||
            document.createElement("div");

and recall that element is the parameter passed to the constructor and this.element is a property we have just created. 

We also need to remember to change the way we add the custom control to the document and use:

this.element.appendChild(c);

In this case either the constructor was called with an element as a parameter in which case the custom control c is added to the DOM or the constructor was called from your own JavaScript code using new and returns a complete object ready for you to do something with.

It is usual to set the winControl property of the containing element to reference the JavaScript object that created the new DOM objects

element.winControl = this;

This allows you to find the JavaScript object following a query of the DOM i.e. element.winControl and find the DOM object from the JavaScript object that created it i.e. this.element.

 

Putting all this together gives use the next refinement of the custom control.

WinJS.Namespace.define("MyControls",
{
 MyCanvasControl: function (element, options){
  this.element = element ||
             document.createElement("div");
  element.winControl = this;
  this.element = element;
  var c = document.createElement("canvas");
  c.width = "500";
  c.height = "500";
  var ctx = c.getContext("2d");
  ctx.fillStyle = "rgb(200,0,0)";
  ctx.fillRect(10, 10, 100, 50);
  this.element.appendChild(c);
 }
});

 

We also have to deal with the problem of the options parameter. This is supposed to allow the user to set initial values for your control either from HTML or in JavaScript. In either case the options parameter is a JSON style set of name value pairs. You can process this one property name at a time if you want to.

For example to allow the user to set the color of the rectangle you could add a color option and process it using:

options = options || {};
this.color = options.color || "rgb(200,0,0)";

and setting the color of the rectangle as:

ctx.fillStyle =this.color ;

The first instruction protects you against options being a null object, the second provides a default value if color isn't a defined property. To set the rectangle to blue say in HTML you would use:

<div
 data-win-control="MyControls.MyCanvasControl
 data-win-options="{color:'rgb(0,0,255)'}">
</div>

 

A much better way of processing the options parameter is to use the supplied function setOptions. This will process the options parameter and add the initialized properties to the object specified.

 

For example:

WinJS.UI.setOptions(this, options);

will add color as a property to the custom control.

Unfortunately if you want to make sure that a property has a default value if the user doesn't provide it you still have to use something like:

WinJS.UI.setOptions(this, options);
this.color = this.color || "rgb(200,0,0)";

 

The setOptions method will also add events to the custom control. If there is a property in the options object that has a name that starts on then it is treated as an event and the property is added as a function - more of this later.

 

The complete custom control is now:

WinJS.Namespace.define("MyControls",
{
 MyCanvasControl: function (element, options){
  this.element = element ||
     document.createElement("div");
  element.winControl = this;
  this.element = element;
  WinJS.UI.setOptions(this, options);
  this.color = this.color || "rgb(200,0,0)";
  var c = document.createElement("canvas");
  c.width = "500";
  c.height = "500";
  var ctx = c.getContext("2d");
  ctx.fillStyle =this.color ;
  ctx.fillRect(10, 10, 100, 50);
  this.element.appendChild(c);
 }
});

It is also worth mentioning that you should assign CSS class names to the various parts of your custom control so that it can be styled. Use the standard CSS classes supplied by Microsoft if you can. To add a class name simply assign to the classname property.