All About Widgets

Widgets are dynamic UI controls that can be integrated within any application. They can be tailored to the application, yet provide reusable, stylistically consistent UI functions. The term “widgets” is widely used within web development, but Mojo widgets are different than other widgets. Mojo widgets have a defined behavior and have many options; they generate complex HTML and are easily styled with CSS.

It helps to understand the HTML that the widget generates. This is especially true for widgets like List and Dialog, for which the application specifies HTML templates that largely define the widget’s appearance.

Declaring Widgets

Widgets are declared in HTML as empty div tags:

<div id="my-toggle" x-mojo-element="ToggleButton"></div>

The x-mojo-element attribute specifies the widget type used to fill out the div when the HTML is added to the page. This can happen in either of the following circumstances:

  • When a scene is pushed and the scene’s view HTML includes widgets.

  • When a widget is specified in an HTML template used by another widget.

  • When the application inserts HTML which includes widgets, and makes a call to explicitly instantiate them.

In the second case, for example, if your scene includes a List widget whose list items include other widgets, a new set of the list item’s widgets are instantiated each time a new item is added to the list.

Setting Up a Widget

Before a widget is inserted into the scene, it must be set up. You should do this in the scene assistant’s setup method by calling the scene controller method, setupWidget().You need to provide three arguments to this call (shown in Table 3-1).

Table 3-1. setupWidget arguments

Argument

Description

Widget ID

The ID or name of the div element in which the widget was declared

Attributes

Object containing the widget’s static properties, normally options or attributes of the widget

Model

Object containing the widget’s dynamic properties, usually data associated with the widget, but occasionally including dynamic attributes

For example, a Toggle Button would be set up this way:

var toggleAttr = {trueValue: "on", trueLabel: "On",
               falseValue: "off", falseLabel: "Off"};
this.toggleModel = { value: "on", disabled: false };
this.controller.setupWidget("my-toggle", toggleAttr, this.toggleModel);

The my-toggle argument specifies the widget being set up. The argument can be either the id or name of the widget’s div element. It’s usually fine to use id, but it won’t be unique if your widget is instantiated more than once. This can happen if the widget is declared in a template for a list item, or if your scene might be pushed multiple times (without being popped). In these cases, use the name attribute instead.

The second argument specifies the attributes for the widget. These are properties that affect the behavior and display of the widget, but are not tied to the actual data being displayed or edited. Widget attributes cannot be changed after the widget is instantiated. A toggle button is a simple binary selector; its attributes include trueValue, trueLabel, falseValue, and falseLabel, among others. The values allow you to toggle between on/off, left/right, up/down, in/out, and so on, while the labels can either track those values or offer different terms for the user.

The last argument specifies the widget’s data model object. This is the actual user data displayed by the widget. The contents of the model object will often change, each time requiring the widget to be updated. In our example, the model includes the toggle’s value and a disabled property, set to false.

The split between attributes and model objects was designed to allow you to use widgets within list entries. The attributes represent the setup shared between list items, and the model provides the per-item data. This will make more sense when you get to the section Lists.

Updating a Widget’s Data Model

When a widget model is changed outside of the widget, the widget will not automatically update and reflect those changes. The application (usually the scene assistant) is required to call the modelChanged() method on the widget’s scene controller, passing the model object that changed. The scene controller will then notify all widgets using that model, so they can properly display the current model data. For example, suppose you disabled the toggle button in our example:

this.toggleModel.disabled = true;
this.controller.modelChanged(this.toggleModel, this);

The first argument to the modelChanged() method is the model object that has changed. Model change notification uses the identity of the model object to determine which widgets are using that model object and then notify them to update.

The second argument identifies which object has changed the model. This ensures that objects are not notified of their own changes to the model.

Scene assistants (and widget assistants, where applicable) will usually simply pass the keyword this. The argument is optional if called from something other than a widget controller.

The modelChanged() method notifies widgets of changes to a model object; if you need to directly change the model, you should use setWidgetModel() instead. While setupWidget() applies to all widgets with the given HTML name attribute, setWidgetModel() only ever applies to a single widget instance. So you must pass the widget’s ID or the actual widget DOM element.

Warning

Calling modelChanged() with an entirely new model object will not update the model. Instead, there will be no change, since the specified model will not be used by any existing widget; no notifications will be generated or received. A common bug occurs when assigning a model to another object then calling modelChanged() using that new object. This will not work; you need to use the original model object for modelChanged() or use setWidgetModel() with the new object.

The following will change the model in our toggle button example:

// Use a new model object in place of the old one:
this.newToggleModel = {value: "off"};

// Set the widget to use the new model:
this.controller.setWidgetModel("my-toggle", this.newToggleModel);

Widget Event Handling

Each widget is supported by events. Where possible, the widget will use common events, such as Mojo.Event.tap or Mojo.Event.propertyChange. Where that’s not possible, widget-specific events are defined, such as Mojo.Event.listDelete or Mojo.Event.listReorder for List widgets, or Mojo.Event.scrollStarting for the Scroller widget.

You should set up event listeners in the scene assistant’s setup method when you set up the widget, by adding the listeners to the div element that declares the widget. For example, the toggle button sends a Mojo.Event.propertyChange when the widget is toggled, meaning that the toggle button’s model changes value.

Using the example toggle button that we’ve been building on, you would set up a listener with code like this:

This.controller.listen("my-toggle", Mojo.Event.propertyChange
  this.handleSelectorChange.bindAsEventListener(this));

For more details on this, look at the section Events, which covers the entire event model for more information, or consult the Mojo.Event API reference in the Palm SDK.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.220.74.231