Widget programming guide

This guide provides a reference to the standard iWidget specification and shows you the additional features available for widgets in the Business Space environment.

As discussed in the Sample widgets overview, Business Space widgets conform to the iWidget specification. In this section a link is provided to that open-source specification followed by additional features for widget development that are found in Business Space.

iWidget specification

The iWidget specification is an open-source specification upon which Business Space widgets are based. Before creating any widget, you should read this specification. Afterwards, it should be used as your guide for creating your own widget. You can find the iWidget specification at the following link:

iWidget v1.0 specification

Predefined event handlers

The iWidget framework provides several predefined events that will be automatically fired without the need for a widget to declare them. For example, an iWidget may choose to override any of the default handlers. The behavior is as follows: if an iWidget defines any of the below event handlers as methods, then these methods will be called, otherwise the default framework event handlers will be invoked.

  • onLoad: Called when the widget first loads up. The widget can initialize the initial view in this handler. There is no event payload.
  • onReload: Called when the widget is reloaded. This event handler is similar to onLoad, however, it is called in slightly different circumstances. When a user is in edit mode and either "Cancel", "OK", or "Apply" is selected, the onReload event handler is called when the view mode is refreshed. This is slightly different behavior than the iWidget spec calls for, since the specification asks that this event fire prior to the reload, rather than during an edit mode refresh of the iWidget content. There is no event payload.
  • onUnload: Called when the widget is about to be unloaded. Important: You must ensure that all Dojo widgets that you have created need to be cleaned up during this event handler. You need to call <widget>.destroyRecursive() to ensure that all child Dojo widgets are cleaned up in terms of memory usage. There is no event payload.
  • onRefreshNeeded: Called when the iContext determines that the widget's data is stale. This event should signal to the iWidget to refresh its data if applicable.

Common dialogs

The iWidget framework provides some common dialogs that you should use when displaying information to the user. The following dialogs are provided by the framework in the following module: com.ibm.bspace.common.util.widget.BSpaceDialogs.

Table 1. Description of common dialogs
Dialog name Description
com.ibm.bspace.common.util.widget.InfoPopup Use this dialog to display informational messages to the user.
com.ibm.bspace.common.util.widget.WarningPopup Use this dialog to display warning messages to the user.
com.ibm.bspace.common.util.widget.ErrorPopup Use this dialog to display error messages to the user.
com.ibm.bspace.common.util.widget.ConfirmDialog Use this dialog to request a confirmation from the user.

This code snippet for a confirm dialog shows how to use the common dialog:

1.   //Show error dialog 
2.   dojo.require("com.ibm.bspace.common.util.widget.BSpaceDialogs");
3.   var errorDialogHolder = document.createElement("div");
4.   var errorDialogDiv = document.createElement('div');
5.   dojo.place(errorDialogHolder, errorDialogDiv, "last");
6.   this._errorDialogWidget = new com.ibm.bspace.common.util.widget.ErrorPopup({dojoAttachPoint: "errorDialogWidget"}, errorDialogDiv);
7.   this._errorDialogWidget.setMessage( user friendly message, verbose details, possible actions );
8.   this._errorDialogWidget.show();
9.   var self = this;
10.   dojo.connect(this._errorDialogWidget, "hide", function () {self._errorDialogWidget.destroyRecursive; });

REST and other HTTP calls

Most widgets need to request data through a Uniform Resource Identifiers (URIs). To request a data through a URI, use the following code:

dojo.xhrGet({ 
  url: this.iContext.io.rewriteURI(uri), 
  load: handler 
}); 

You can use a similar approach for the other HTTP actions (PUT, POST, DELETE).

Widget modes

iWidget has specific mode handlers (eg. onview, onedit, and so on) for each possible mode that is specified in the supportedModes attribute of the iWidget's definition. For example, if an iWidget supports view mode and edit mode, you need to create onview and onedit methods in the widget's implementation. An onview method would be coded as follows:

onview: function(){
  this.setGridDimention();
  this.showFilterPattern();
  this.findModels(this.listModels); 
}

The iWidget runtime guarantees that the proper mode event will be fired after an iWidget is loaded (eg. we can assume that onview() will be called after onLoad()). Therefore, your code for these mode events would be as follows:

onLoad: function(){
  ...
  ... 
}

onview: function(){
   this.setGridDimention(); 
   this.showFilterPattern(); 
   this.findModels(this.listModels); 

Additional handling for edit mode

Your widget needs to add and manage the OK, Apply, Cancel, and Restore buttons that appear on the edit mode view. There is a helper class available in the common utility resource that all Business Space widgets will include. This helper class allows the creation of the edit mode buttons. To use this helper class follow these steps:

  1. A widget that would like to use the common buttons, which is recommended for all Business Space widgets, needs to add the following require statement:
    dojo.require("com.ibm.bspace.common.util.widget.BSpaceEditButtonPanel"); 
  2. Next, the widget needs to create a placeholder for the buttons (eg. editButtonPanelPlaceholder) within the edit mode content fragment.
    <div> 
        <div class="editButtonPanelPlaceholder"></div>
    </div>
  3. You add the buttons to your edit mode markup by placing the following code snippet into the beginning of your onedit() method:
    var temp = this.iContext.getElementByClass("editButtonPanelPlaceholder");
    editButtonPanelPlaceholder = temp[0];
    var editButtonPanel = new com.ibm.bspace.common.util.widget.BSpaceEditButtonPanel({parentWidget: this, iContext: this.iContext}, editButtonPanelPlaceholder);
  4. Add methods to your widget to handle the edit mode button actions. Add these methods: onEditOk(), onEditApply(), onEditCancel(), onEditRestore(). In addition, the following information on these buttons assumes that you also have the onRefreshNeeded() and onSave() methods available in your existing widget.
    • onEditOk method: This method is needed to handle the saving of the widget attributes. The onEditOk method can return a boolean value to indicate if the OK action should continue. This is important if the widget needs to do some validation checking at this point. If the method returns true, then after the onEditOk method returns, the helper will issue an onModeChange event to notify the framework to change back to view mode. If the return value is false, no action will be taken (this is where you would need to update the validation errors and try again). If no value is returned by the method, true is assumed.
    • onEditApply method: This method is needed to handle the saving of widget attributes. Widgets classes also need to have an onRefreshNeeded() method as this event will be fired immediately after an onEditApply() method to refresh the widget's appearance. The onEditApply method can return a boolean value to indicate if the Apply action should continue. This is important if the widget needs to do some validation checking at this point. If the method returns true, then after the onEditApply method returns, the helper will issue an onRefreshNeeded event to notify the widget to refresh its view. If the return value is false, no action will be taken (this is where you would need to update the validation errors and try again). If no value is returned by the method, true is assumed.
    • onEditRestore method: This method is needed to handle the restoring of the widget attributes. Typically a widget holds a cache of the widget attributes prior to a user's modifications. This method ensures that the correct attributes are set. This can be done by using the onSave() method as part of the implementation of this method. A widget's classes also need to have an onRefreshNeeded() method as this event will be fired immediately after onEditRestore() to refresh the widget's appearance. The onEditRestore method can return a boolean value to indicate if the Restore action should continue. If the method returns true, then after the onEditRestore method returns, the helper will issue an onRefreshNeeded event to notify the widget to refresh its view. If the return value is false, no action will be taken. If no value is returned by the method, true is assumed.
    • onEditCancel method: This method is needed to handle the cancel of the edit mode. This method usually means that the widget does not need to do anything, meaning it should not call the onSave() method since this is a cancel request. The onEditCancel method can return a boolean value to indicate if the Cancel action should continue. If the method returns true, then after the onEditCancel method returns, the helper will issue an onModeChange event to notify the framework to change back to view mode. If the return value is false, no action will be taken. If no value is returned by the method, true is assumed.

Size change handling

Widgets must handle the onSizeChanged event by supplying an onSizeChanged(iEvent) method as defined by the iWidget specification. The payload of the iEvent will have properties for the newWidth and newHeight values. This method should resize the widget according to the new dimensions.

When the widget is minimized, the values for newWidth and newHeight will both become 0. In all other cases, the values for newWidth and newHeight will represent the actual dimensions that the widget should be, after the onSizedChanged event.

The following code shows how to use the onSizeChanged method:

onSizeChanged: function(iEvent) { 
      var data = iEvent.payload; 
      if (data) { 
         alert("new height: " + data.newHeight); 
         alert("new width: " + data.newWidth); 
      } 
   }

Catching exceptions and handling errors

Widgets and framework classes should practice defensive programming and try to catch and handle exceptions in all top level methods. This means that widgets should encapsulate all of the following methods in try/catch block statements:

  • onLoad
  • onReload
  • onUnload
  • onSizeChanged
  • onedit
  • onview
  • onNavStateChange
  • onRefreshNeeded
  • You should also encapsulate any widget-specific event handler with a try/catch block statement.

Iterative development

When you create a widget in Rational Application Developer or WebSphere Integration Developer, there will be many Dojo errors shown in the JavaScript editor. These errors do not prevent the widget from working. To remove the errors, edit the .project file in the workspace. Remove the jsNature line (<nature>org.eclipse.wst.jsdt.core.jsNature</nature>) and then refresh the project in the workspace.

When making a change to a widget, you should redeploy it. Then in the browser, logout of Business Space, clear the cache in the browser and then login to Business Space.

For the initial deployment in Rational Application Developer or WebSphere Integration Developer, you can use the add/remove projects dialog in the server view, rather than exporting an EAR and using the admin console to install it. Since the context root, defaults to the WAR project name, make sure you refer to the correct name for the 'url' tag in the widget endpoints XML file.

For subsequent deployments, you can select the option in the server view to republish the project to the server.

You have looked at the key iWidget specification that Business Space widgets are based upon and have learned some key areas that are unique to Business Space. In Representational State Transfer (REST) APIs you will find the REST APIs that are available to you for IBM business process management products. The REST APIs let you access functions at runtime in the IBM business process management products.