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: Plugins / Archetypes
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:
.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.
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:
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.