The custom control architecture

As we saw in the previous section, custom controls extend the functionality of a normal XForms control, and can therefore make use of the same features. For example, if a ref or bind attribute is used on the control, it will automatically be bound to the specified data in the XForms model, and so receive notifications when either the data or the model item properties (MIPs) change.

Similarly, as long as the custom control dispatches the correct event to the model when data is changed by the user, the author does not need to worry about keeping the model up-to-date.

The events that can pass between the custom control and the XForms model can be represented as follows:

Informing the backplane that the control is ready

Once a custom control has completed any necessary initialisation, the fp-uiready event must be dispatched. Although the event is used to let the formsPlayer framework know that the control is ready, the target for the event is the custom control itself, and the event will bubble to the formsPlayer framework.

Dispatching the event is typically achieved like this:

var evt = this.ownerDocument.createEvent("Event");

evt.initEvent("fp-uiready", false, false);
this.dispatchEvent(evt);

Notification from the backplane that the data has changed

The XForms model provides notifications to forms controls that the value of the bound node has changed. The XForms framework in turn passes on this notification to the custom control, via the fp-putvalue event.

The custom control will typically register for this event in the constructor:

var theListener = this.document.getFeature("Events.listener", "2.0");

theListener.handler = this.handlerPutvalue;
this.parentElement.addEventListener("fp-putvalue", theListener, false);

A handler for the fp-putvalue event can use the Event object (as defined in DOM 2 Events) to obtain the new value, and will generally check that it is different to the previous value before doing something with it:

function handlerPutvalue(event)
{
  switch (event.type)
  {
    case "fp-putvalue":
      var newVal = event.newValue;

      if (this.currentVal != newVal)
      {
        //do something here
        this.currentVal = newVal;
      }
      break;

    default:
      break;
  }
  return;
}