Developing Sidebar Widgets

In XperienCentral, archetypes are used to generate the files and basic directory structure for a simple, but fully functional plugin. Sidebar widgets are technically an XperienCentral plugin. Before following the steps contained in this topic, you might want to read the general introduction on Sidebar Widgets in order to get some context. Some basic knowledge of XperienCentral plugins will also help. This topic explains how to generate a plugin for adding a sidebar widget to the XperienCentral Workspace. Using the generated source files, you can then modify them as desired to create your widget. This starting point saves you a lot of time creating files from scratch and copying and pasting code.



In This Topic



Creating a Sidebar Widget

There is an archetype available in XperienCentral for generating Sidebar widgets. Executing the following command in a Command prompt to generate the "Hello World" sidebar widget using the sidebar widget archetype:

mvn -s settings.xml archetype:generate -DinteractiveMode=false -DarchetypeGroupId=nl.gx.webmanager.archetypes -DarchetypeArtifactId=webmanager-sidebarwidget-archetype -DarchetypeVersion=<xperiencentral-version> -DgroupId=com.gxwebmanager.helloworld -DartifactId=helloworldsidebarwidget -Dclassprefix=HelloWorld

where:

<xperiencentral-version> is the version of XperienCentral you are using. The last three parameters (groupId, artifactId and classprefix) should be modified for your particular plugin. The groupId and artifactId are used not only by XperienCentral but also by Maven (click here for more information). The groupId is also used as a Java package name and should in most cases be the same as the groupId for other components in the same project. The artifactId is also used as a unique identifier (the ID for the plugin). The class prefix is used as a prefix for different Java classes which are generated. Give it a meaningful, but not too long name.

After executing the above command, a directory named "helloworldsidebarwidget" will be created.

Generating the widget basically means automatically creating the source code. Once generated, the source code needs to be built. To build the archetype, execute the following command in the directory where the archetype was generated:

mvn -s settings.xml clean install

Thereafter, it can be deployed just like any other plugin by navigating to Configuration > Plugins in the XperienCentral Workspace. After installing the plugin, you need to refresh the XperienCentral Workspace in order to make new widgets available to be added to a Sidebar.


Related subjects: PluginsArchetypes


Back to top



The Generated Files and Directories

After importing the contents of this directory in an IDE you will see a structure like this:

Activator and other Java code

The most interesting files for the Sidebar widget are the HTML, .CSS and JS files in the resources, since these are specific for widget plugins. The Activator class is the starting point of every plugin and defines the different parts the plugin consists of and what should happen next. For general information on XperienCentral plugins you can find information on the Plugins page and its subpages, such as the section about Authorization in Plugins. One part of the Activator is specific for widget plugins, namely how a DojoModule is defined. The DojoModule Java class is used to register the client-side component in XperienCentral to define where to find its client-side code when loading it and to access language-specific strings. Consider the following code snippet:


    private DojoModule getSidebarModule() {
        // The module id should start with the plugin id
        String moduleId = WCBConstants.WCB_ID + ".sidebar.helloworldsidebarwidget";

        // The path maps onto the src/main/resources/dojotype/<plugin ID>/sidebar/${classprefix}.js file
        String path = WCBConstants.WCB_ID + "/sidebar/HelloWorld";
        DojoModule module = new DojoModuleImpl(moduleId, ModuleType.SIDEBAR_WIDGET, TITLES, DESCRIPTIONS,
                "GX Software B.V.", "resources/helloworldsidebarwidget.png", path);
        return module;
    }


Above, you can see how the icon (helloworldsidebarwidget.png) is registered. This is the icon that is associated with the widget in the Workspace. You can also see that TITLES and DESCRIPTIONS are passed to the constructor of the Dojo module. These are maps that define the title and description of the widget in the supported languages. The description is shown when adding the widget to the sidebar. These two constants indirectly refer to the message files for Dutch and English (messages_en_US.properties and messages_nl_NL.properties) where the actual strings are defined.


The DojoModule defined here is added to the ComponentDefinition like this:


        // Add the sidebar widget
        widgetDefinition.setDojoModules(new DojoModule[]{getSidebarModule()});

languageResource.js Files

The languageResource.js files define the conversion from technical identifiers to easy readable texts in different languages. There is one file for each supported Workspace language. The default resource file is for English and the one in the NL directory is for Dutch. If other languages are supported, they are contained in a directory which is named after the ISO 639-1 standard langugae identifier codes (SP for Spanish, FR for French, DE for German, and so forth. The same identifiers are defined in all language resource files, but the strings they refer to are translated in the different languages. The language definitions are in JSON format which is very commonly used on the internet:


define({
	root : {
		title : "Title:",
		urlTitle : "URL Title:",
		save : "Save",
		savedSuccessfully : "Saved successfully",
	},
	'nl' : true
});

HelloWorld.html


<div class="helloworldsidebarwidget">
  <div class="divRow">
    <div class="propertiesLabel">${i18n.title}</div>
    <div class="propertiesValue" data-dojo-attach-point="_titleNode"></div>
  </div>
  <div class="divRow">
    <div class="propertiesLabel">${i18n.urlTitle}</div>
    <div class="propertiesValue">
      <input type="text" data-dojo-type="dijit/form/TextBox" data-dojo-props="trim:true" data-dojo-attach-point="_urlTitleNode" />
    </div>
  </div>
  <div class="divRow">
    <div class="buttonRow"></div>
    <div class="propertiesValue">
      <button data-dojo-type="dijit/form/Button" data-dojo-attach-point="_saveButton">${i18n.save}</button>
    </div>
  </div>
</div>


The above is an example of an HTML template which is partial HTML that defines the user interface of the Sidebar widget. This HTML file, together with HelloWorld.js defines a Dojo widget. If you're not familiar with the Dojo Toolkit, see the Sidebar Widgets topic.

There is always a tag, in most cases a <div>, surrounding the rest of the HTML.

  • data-dojo-type - defines the type of widget to include, for example a textbox or a button.
  • data-dojo-props - contains any configuration that needs to be passed to the constructor upon instantiation (more info).
  • data-dojo-attach-point - is used to refer to a given element from the JavaScript code (see _saveButton in Event handling).
  • class - is used for CSS styling and to look up groups of elements from the JavaScript code.

Labels like ${i18n.urlTitle} insert the language dependent texts defined in the languageResource.js files.

HelloWorld.css

Common CSS styling of the HTML is defined in HelloWorld.html. Note that every CSS selector starts with the identifier of the plugin (Artifact ID or plugin ID). This matches the class of the top level tag in the HTML. It is important to separate the CSS of different widgets from each other and from other CSS used within XperienCentral. When you start adding your own CSS selectors, remember to always start by matching this identifier. For example:


Part of the CSS
.helloworldsidebarwidget {
	margin: 8px;
}

.helloworldsidebarwidget .propertiesOverview {
	display: table;
    width: auto;
}

HelloWorld.js

The HTML and this JS together form a component which is styled by the CSS. Refer to the introduction if you are not familiar with the Dojo toolkit.

Basic Dojo Class Structure

The structure of the generated Sidebar widget code (the typical Dojo file structure) is shown below. It defines a widget, which is a Dojo class. The define part defines the dependent modules in AMD format. The modules, which are Dojo classes, are mapped to variables to allow access to them. This is done by adding the variables as arguments to the function statement following the define. These variables must be in the exact same order as the module references (this is a common source of errors).

The array passed to the declare statement defines the classes this Dojo class inherits from. The constructor and postCreate functions have special meanings in Dojo and are called during different stages of the initialization of the class. First constructor initializes class variables and then the postCreate  initializes the user interface. The methods are not mandatory and often there is no need to override the constructor (more information from the Dojo documentation).


define([
  ...
  "dojo/text!./HelloWorld.html",
  ...
  "dojo/i18n!./nls/languageResource",
  ...
  "dijit/form/TextBox",
  "dijit/form/Button"
], function (..., template, ..., languageResource, ...) {

  return declare([SidebarContentItemWidget, _TemplatedMixin, _WidgetsInTemplateMixin], {
    templateString: template,
    i18n: languageResource,

    // Attach points

    // Variables

    constructor: function () { ... },

    postCreate: function () { ... },
    
    _xxxxxxx: function () { ... },

    _yyyyyyy: function () { ... }    
  });
  
});


Prefixing a function name with an underscore (_) is a convention for telling human readers of the code that a function is private. This encapsulation is not enforced by JavaScript interpreters. Never use properties and methods of other classes which are prefixed with an underscore.

Calling the Parent (super) Constructor

When overriding methods (functions) in Dojo, you should always call the parent method unless you explicitly want to prevent it from being executed. Simply use the arguments variable as in the example below to pass on the method arguments. This is variable is available in all JavaScript functions, not only in Dojo.


    postCreate: function () {
      // simple super call with the same arguments.
      this.inherited(arguments);
      ...
    }

Event Handling

The implementation of XperienCentral widgets is based on events. This means the JavaScript code subscribes to events to be able to listen to and react, for example, a button being clicked or that the page shown in the content area has changed. To listen to an event, you define an event handler, which is a normal JavaScript function. The function will be called every time the event occurs.

Subscribing to an Event

The code below, extracted from the archetype shows how to connect the event handler function _updateData to the event contentItemChange and the event handler _handleSave to the click event of the button called _saveButton:


      // to prevent memory leaks when the widget is destroyed
      this.own(
        // update the view when the content item changes (event).
        on(this, "contentItemChange", lang.hitch(this, this._updateData)),
        // add a handler for the save button
        on(this._saveButton, "click", lang.hitch(this, this._handleSave))
      );


The Dojo keyword on is used to subscripe to events. The lang.hitch(...) construction is a trick to pass on the this reference, referring to the widget itself, to the event handler when it is called.

The on calls are surrounded by a this.own method. It ensures that the event handlers are freed when the widget is destroyed. See Destroyable in the Dojo documentation for more details.

How do you tell that there is an event called contentItemChange and how can you find other XperienCentral events available for subscription? If you look at the code for the event subscription above, you see that the fist argument to the on call is the this reference. That means the event is thrown on the widget object itself. For the _saveButton click event this is quite logical because the widget contains the button. But what about the contentItemChange event? Since it is not defined in the widget it is likely it comes from a parent class. There are three parent classes and only one of them is defined in XperienCentral - that is the class SidebarContentItemWidget.

Finding events available for subscription for standard Dojo widgets can be done in a similar way. In HelloWorld.html you can see that the full type of the button is dijit/form/TextBox. Look this class up in the Dojo API Documentation - expand the Event Summary to see all available events.


Back to top



Adding the Widget to XperienCentral

Generate, build and deploy the plugin containing the "Hello World" widget in XperienCentral. In the Workspace. The widget is now available to be added to a Sidebar. Click the (+) icon on one of the sidebars and click the [Add] button for the "Hello World" widget. The "Hello World" widget will be added to the Sidebar:



Back to top



Training Resources

GX Software offers courses in developing plugins for XperienCentral. These highly recommended courses put you on the fast track to developing plugins that add custom functionality to your XperienCentral installation. For complete information, see the Training Courses topic on our corporate website.


Back to top