loading table of contents...

7.13.4.2. Configurable and Stateful Widgets

The WidgetType interface also features the creation of an editor component for a widget at runtime. Again, if you opt to implement the interface yourself, you have to provide this functionality from scratch. If you choose your type to extend ComponentBasedWidgetType, you simply have to add an editor component, just as you did for the widget component. Consequently, the EXML definition for the SimpleSearchWidgetType for simple search widgets that are configurable at runtime looks as follows:

<exml:class ... >
  ...
  <editor:componentBasedWidgetType
          name="..."
          description="..."
          iconCls="...">
    <editor:widgetComponent>
      <editor:simpleSearchWidget/>
    </editor:widgetComponent>
    <editor:editorComponent>
      <editor:simpleSearchWidgetEditor/>
    </editor:editorComponent>
  </editor:componentBasedWidgetType>
</exml:class>

Example 7.55. Simple Search widget Type with Editor Component


Now widgets of this type have their own editor component when a widget on the dashboard is in edit mode.

However, without further wiring, the changes a user makes in edit mode do not carry over to the widget component. For the simple search widget it is expected that the user can choose a search text and content type in edit mode and that the widget shows a corresponding search result in widget mode. To make this happen, SimpleSearchWidgetEditor has to implement the StateHolder interface. The method getStateValueExpression() has to be implemented in a way that the value expression refers to a simple JavaScript object containing the configuration properties to be applied to the widget component. Thus, for the simple search widget, these properties are searchText and contentType.

See section Section 7.7, “Storing Preferences” for details of how the state values are persisted and for the limits on the allowed objects.

You could just implement the StateHolder interface yourself. For convenience, CoreMedia recommends, that you let your editor component extend StatefulContainer. This component inherently implements StateHolder. It can be configured with a list of property names along with default values and automatically takes care of building a state model bean from them. This state model bean is the basis for the evaluation of the value expression that is returned via getStateValueExpression(). Additionally, the bean can be consulted via getModel() from subclasses of StatefulContainer. This can be utilized for binding the model state to the user interface state. The following listing exemplifies this for the case of SimpleSearchWidgetEditor:

<exml:component ...>
  ...
  <ui:statefulContainer layout="form"
                        properties="searchText,contentType">
    <items>
      <editor:contentTypeSelector fieldLabel="..."
                                  width="auto"
                                  fieldClass="">
        <plugins mode="append">
          <ui:fullWidthPlugin/>
        </plugins>
        <editor:contentTypeValueExpression>
          <ui:valueExpression expression="contentType"
                              context="{getModel()}"/>
        </editor:contentTypeValueExpression>
      </editor:contentTypeSelector>
      <textfield fieldLabel="..."
                 width="auto">
        <plugins>
          <ui:bindPropertyPlugin bidirectional="true">
            <ui:bindTo>
              <ui:valueExpression expression="searchText"
                                  context="{getModel()}"/>
            </ui:bindTo>
          </ui:bindPropertyPlugin>
          <ui:immediateChangeEventsPlugin/>
          <ui:fullWidthPlugin/>
        </plugins>
      </textfield>
    </items>
    <ui:propertyDefaults>
      <exml:object contentType="{ContentTypeNames.DOCUMENT}"/>
    </ui:propertyDefaults>
  </ui:statefulContainer>
</exml:component>

Example 7.56. Simple Search widget Editor Component


This editor component for the simple search widget extends StatefulContainer and is configured to build a state model for the two properties searchText and contentType. For the content type property, a default is set. The editor component offers the user a combo box for selecting a content type and a text field for entering a search text. The user's input is tied to the state model via value expressions that use getModel() (inherited from StatefulContainer) as their context. This results in keeping the state model updated. Implementing the StateHolder interface yourself is not necessary. It is automatically taken care of by StatefulContainer on the basis of the always up-to-date state model.

All in all, this results in the simple search widget editor being stateful. When the user switches between widget mode and edit mode for this widget, the editor will keep its state (search text and content type). The state is only lost if the user selects a different widget type in edit mode.

In some cases, it might be useful to not only have the editor of a widget being stateful, but also the widget itself. This can be realized in the same way shown here for the editor: by implementing the StateHolder interface.