The BPM UI Coach View set

IBM BPM has progressed through many iterations over the many years of its existence. From the original Lombardi Teamworks, through IBM WebSphere Lombardi Edition, through to todays IBM BPM offerings. Throughout that time, changes have been made relating to how a developer creates screen definitions (coaches). The single largest change occurred with the arrival of the Coach View technology. Coach Views provided a "composable" set of building blocks that could be used to construct the screens. The Coach Views provided by IBM included simple text inputs, checkboxes, tables and a few others. The secret sauce of the Coach View technology was that customers and other vendors could build their own Coach Views which then became additional components in the palette of available building blocks used to construct the screens. Over the years, IBM steadfastly held to the belief that the simple set of Coach Views provided with the product were sufficient and that there were enough additional Coach Views in the public domain and from third party vendors that IBM need not invest additional effort producing richer of more numerous instances.

Of the multiple vendors producing Coach View sets, one stood out. That was the SPARK UI set from Salient Process. IBM examined the available Coach View sets from a variety of vendors and chose SPARK UI for acuisition. After purchase and a period of harmonizing the SPARK UI set with IBM's core look and feel, the release of 8.6.0 saw the arrival of a Coach View set that IBM calls BPM UI. To all intents and purposes, this is the SPARK UI set of Coach Views now exclusively owned by IBM and distributed with the base BPM product. The super rich and numerous Coach Views now available with BPM that were previously known as SPARK UI, are the core of the remainder of this chapter.


Each SPARK UI Coach View will have its own configuration section. Some aspects of the configuration will be specific to the type of Coach View while others will be common. The configuration features are broken into categories:

  • Formula

  • Behavior

  • Appearance

  • Performance

  • Responsive

  • Events

The Control tree

Within a Coach, controls can be considered to exist in a hierarchical structure just like a file system tree. The top of the page is called the root and every other control is either a child of root or a child of some other control which will eventually be able to be traceable back up to the root.

Every control can be classed as either a container or an element. A container is distinct from an element as the container may have child controls while an element may not. An addressing scheme is available which allows us to locate any individual control in the tree. If an address starts with "/" then we are considering our navigation from the root downwards. If the address does not start with a "/" then we are working contextually relative to some reference control. Since each control is a child of some other control (except for the root) then we can think of the notion of a parent of a control. If we are navigating relative to a control, we can reference its parent with the string "..". A convenience is that a control that shares the same parent (i.e. a sibling control) can be reference with just the name of the control. To access a specific control using an absolute path, we can use the function:


For example:


will return the control called "Text1" that is an immediate child of theroot.

To determine the path name of a view, we can use view.ui.getAbsoluteName().


The Events category defines event types that the Coach View publishes upon when something interesting happens such as a user interaction. When an event fires, JavaScript code that is associated with the event entry is called. This JavaScript can be inline or can be a function call to a JavaScript function that is within scope. Let us look at an example. Imagine we have a button Coach View that looks as follows on the screen:

In the Events of that Coach View, we can define the following:

Notice that we have coded "On Click". This says that the code will be executed when the button is clicked. This code is inline code.

We can also code up a JavaScript function in a Custom HTML Coach View that might be:

  function buttonClicked(cv) {  
    alert("Button clicked\!");  

And then in the "On Click" handler we can define:


as the code to be executed.


To use the value of a control we can use:


This is so commonly performed that a short hand is available of the form:

@ {Name}


When scripting views, we can refer to a view by its identity. We have a couple of techniques for referencing the view:

  • page.ui.get({name})

  • ${name}

  • me

When an event is called, there is a context in which that event executes. It includes the following variables:

  • me - The control that issued the event.

  • view - The parent of the control that issued the event.


The layout containers are:

  • Well

  • Panel

  • Collapsible Panel

  • Tab Section

  • Stack

  • Modal Section

  • Horizontal

  • Vertical

  • Table Layout/Row/Cell

  • Horizontal Split


Icons are available in the SPARK UI and are based upon the "" set that can be found here.


Making REST Calls from a Coach

The Controls


The Alerts control is responsible for showing alerts. To show an alert, a method called appendAlert() must be called on the alert control instance. The signature of the appendAlert() is:

appendAlert(title, text, style, timeout, id, data)

See also:

Area Chart

See also:


The badge can have three shapes:


See also:

Bar Chart

See also:


At runtime, we would normally call "appendItem()" to add a new level to the bread crumb trail.

A default view looks as follows:

See also:


The button is a classic UI component that presents a visualization of a button that can be pressed. It can be styled, colored and sized. It can also include an icon. The eventing mechanism allows arbitrary logic to be invoked when it is clicked.

Here are some examples:




Default with icon

See also:

Caption Box

The caption box encloses a single additional SPARK UI control and adds a specialized label around it. The position and style of the label can be highly customized.

See also:

Check Box

See also:

Checkbox Group

The isChecked() method returns true or false depending on whether or not the check box is checked.

See also:

Collapsible Panel

The Collapsible Panel is a container which can be collapsed down to a single entry and re-opened again. A group of collapsible panels can be defined that are linked together. When one is opened, all the others close ensuring there is only one open at a time.

See also:


This control provides SPARK UI diagnostics/debugging capabilities.

See also:


The Data control provides a binding between BPM data (teamworks data) and SPARK UI data. It is a non-visual control and hence is used exclusively in JavaScript most commonly in event handling. The control should be bound to a human service variable. The control exposes setData() and getData() to set and get the value of the variable.

See also:

Data Export

The Data Export control allows one to export data as an Excel spreadsheet or as a CSV document.

See also:

Date Picker

Pick a date (not a time nor a date and time).

See also:


See also:

Deferred Section

It takes time for a set of Coach Views to load into a Coach. We may wish them not to be loaded immediately but instead deferred to a point in the future.

See also:

Device Sensor

Determine nature of the device (browser, platform etc) that the Coach is running upon and be able to use that information to control the appearance of the Coach.

See also:

Donut Chart

See also:

Dual List

See also:

Event Subscription

See also:

Exit Safeguard

Prompt the user for a confirmation before closing the Human Service browser window/tab.

See also:

Geo Coder

See also:

Geo Location

See also:

Horizontal Layout

See also:

Horizontal Split

See also:


The icon can be one of the font-awesome icons.

See also:


See also:

Input Group

See also:


See also:


See also:

Line Chart

See also:

See also:


See also:

Masked Text

This control provides an input field which controls the input format of the input field. The primary data entered that has been entered into the field can be retrieved through "getMaskedText()". See also:

Modal Alert

See also:

Modal Section

The modal section provides a dialog box that can contain other controls. A Coach user can't interact with controls not in the dialog box until the dialog is disposed. This is what is known as "modal" interactions.

When working with the Modal Section in Web PD it has the following appearance:

Notice that there doesn't appear to be anywhere to drop its contained Coach Views. If we click on the control within Web PD, we will find that it expands:

Now we can place content within it. Clicking again on the "red X" at the top left, will once again collapse it.

We should set the visibility of the Modal Section to "None" otherwise it will be visible when the page is initially loaded … and this isn't what one would normally want. However, we seem to have a new problem. If we set the "Visibility" of the control to be "None", it disappears in the PD editor. This feels like a PD bug. To work around this, instead of explicitly setting the visibility to none, we can specify a script rule that returns "NONE".

A good candidate for a child of the Modal Section is a Panel. By using a Panel we get a header and content areas that looks very much like a dialog. If we set the icon of the Panel to be "close" then we get a pleasing close button:

On the Panel control, we can catch a click on the close button via an event which we can then use to hide the dialog:

Another useful addition is to place a Panel Footer in the panel and in the panel footer we can place a button. This provides an almost identical look and feel to what users expect from a dialog box. Placing a button in a footer makes it appear on the left of the dialog and if we want it on the right, add a horizontal layout that is tight and right justified and place the button within that.

See also:

Multi Purpose Chart

See also:

Multi Select

The Item List property in the Items section defines a list from which the items will be chosen. To determine when an item selection has changed, we can use the "On Change" event. We can retrieve a list of selected items using the "getSelectedItems()" method.

Here is an example of usage.

The data for the select comes from name/value pairs where the name is shown as the label in the list and the value is the corresponding value. The data can come from either static description, a service call or a configuration option.

See also:

Navigation Event

The Navigation Event is a non-visible component used to perform a boundary event transition. Once we have a reference to the control in JavaScript, we can invoke the fire() method on it to cause the corresponding boundary condition transition. An alternative to fire() is confirmAndFire() which displays a simple dialog box which asks for confirmation.

See also:


Display a visible "note" to the Coach user.

See also:


See also:

Output Text

This control provides an output text field.

See also:


The Panel is a container control that provides a header and a content area. The header can also have an icon which appears on the right. A click on the icon can be captured through an event.

See also:

See also:

Panel Header

See also:


See also:

Pie Chart

See also:


See also:

Popup Menu

Create a popup menu on another control.

A menu item is composed of a set of properties:

  • Command - (command (String))

  • Item Type - (itemType (MenuItemType))

  • Icon - (icon (String))

  • Item Text - (itemText (String))

  • Badge shape - (badgeShape (MenuBadgeShape))

  • Badge color - (badgeColor (TooltipColorStyle))

  • Badge text - (badgeText (String))

See also:

Progress Bar

See also:

QR Code

See also:

Radio Button

See also:

Radio Button Group

It is not uncommon to want to have a radio button be part of a group of radio buttons such that when one is selected, any others in the group become unselected.

Here is an example:

The data for the group comes from name/value pairs where the name is shown as the label of the radio button and the value is the corresponding value. The data can come from either static description, a service call or a configuration option.

See also:

Responsive Sensor

See also:

Service Call

We use this view to define a BPM hosted service that can be invoked from the Human Service. An instance of this view has an "execute()" method that, when invoked, will result in the execution of the corresponding bound service. Parameters can be passed as input. For example:


The signature of the target service must have:


  • data (ANY)


  • results (ANY)

  • error (AjaxError)

Within Web PD, when we create a new service, what is created is an External Service and not an AJAX service. This seems to work but results in a not authorized when called. We can fix that by visiting the Overview tab of the service and changing its exposed configuration:

In the callback, we can use the getResult() method to retrieve the returned data.

In the callback we can code @functionName to invoke a function in our code.

See also:

Service Data Table

Very similar to the Table control, this control calls a back-end service that, when it returns, will use the data returned from it to populate the table.

We can call refresh(true) to cause the service to be called and populated.

See also:


See also:

Single Select

See also:


See also:


See also:


See also:

Status Box

Attach a status box to another control.

See also:

Step Chart

See also:


See also:


We can ask the switch whether it is "on" or "off" using the "isChecked()" method. If the switch is on, the return is true otherwise if the switch is off, the return is false.

See also:

Tab Section

See also:


The columns property of the table is an array of TableColumn.

We can obtain the selected record using getSelectedRecord().

Imagine we have a button in a row in the table. When the button is clicked, we want to do something related to the row that contained the button. How can we determine which row the button was in that was clicked?

When the button is clicked, we know the identity of that button. It can be found in the me variable. We can then ask the table to return the row that contains the button using:


Once we know the row, we can get the data using getData().

Imagine we have obtained (or calculated) a new set of data to be shown in the table. How do we visualize that data?

See also:

Table Layout Cell

See also:

Table Layout Row

See also:


In the event handling:

On Change provides environmental data as the variables "newText" and"oldText".

On Input provides environmental data as the variables "current" and "potential". The potential is the complete new text.

See also:

Text Area

See also:

Text Editor

See also:

Text Reader

See also:


See also:


The tooltip provides a container. Coach Views placed in the container will then have the tooltip shown associated with them because they are contained within the container.

See also:

Type Ahead Text

See also:


This control is able to stand in for other controls including Text, Masked Text, Single Select, Date, Decimal and Integer.

See also:

Vertical Layout

See also:


See also:


See also:

New Controls

See also:


To be a developer of SPARK UI one must understand the architecture.

The first thing to realize is that there is no code in the common event/callback functions known as load(), change(), unload() etc. Instead, the code is kept in a single JavaScript file which explicitly defines the functions required by CoachNG. There are several reasons for this. First it keeps the source integrated and together and hence easier to edit and work upon. It also allows us to run JavaScript minifiers and obfuscators over the code. In addition, having a single JavaScript source file causes it to be browser cached and is faster. If this wasn't enough, we will also find that when performing Chrome debugging, we can quickly get to our code through the underlying file.

For example, the CoachNG onLoad() function would be defined in the control as:


The source file that contains these functions is called "BPMExt-Control-<name>.js".

The SPARK UI controls adhere to naming conventions. Specifically:

  • BPMExt-Control-<name>.js - The source of the JavaScript that constitutes the control.

  • BPMExt-Control-<name>.css - CSS needed for this specific control.

  • BPMExt-Control-<name>-Palette.png

  • BPMExt-Control-<name>-Preview.png

  • BPMExt-Control-<name>-Preview.js

  • BPMExt-Control-<name>-Preview.html

The typical included scripts are:

  • BPMExt-Core.js (

  • BPMExt-Control-<name>.js

  • BPMExt-Control-<name>.css

  • spark-fonts.css

  • spark.css

  • loader.js

The AMD dependencies are:

  • com.salientprocess.bpm.views/bpmext bpmext

  • utilities

  • dojo/dom-class domClass

  • dojo/dom-attr domAttr

  • dojo/dom-construct domConstruct

A Coach view is initialized with a piece of inline JavaScript coded as follows:

this, utilities, bpmext, domClass, domAttr, domConstruct, fastclick

This causes the function called "bpmext_control_Init<Name>" to be invoked with the local "this" in the function being executed being the Coach View itself. This is a common JavaScript technique. This function is defined in the corresponding BPMExt-Control-<name>.js.

The structure of a Coach View is:

  • Create and populate the this._instance

  • Create and populate the this.constructor.prototype._proto

  • Create and populate the exposed functions at this.constructor.prototype

  • Create a load function at this.constructor.prototype.load

  • Create a view function at this.constructor.prototype.view

  • Create a change function at this.constructor.prototype.change

  • Create a change function at this.constructor.prototype.validate

  • Create a change function at this.constructor.prototype.collaboration

  • Create a change function at this.constructor.prototype.unload

The load function must call bpmext.ui.loadView(this) if the control is a view or it should call bpmext.ui.loadContainer(this) if the control is a container.

The unload function must call bpmext.ui.unloadView(this).

When we execute the loadView() call, a set of pre-defined functions are implicitly added to our view including:

  • addClass()

  • getData()

  • hide()

  • isBound()

  • isEnabled()

  • isValid()

  • isVisible()

  • propagateUpValueChange()

  • recalculate()

  • setData()

  • setEnabled()

  • setValid()

  • setVisible()

  • show()

  • triggerFormulaUpdates()

The "_instance" view property

We have adopted a convention that each control will have a property called "_instance" that is an object that will hold our private instance state. One of the primary reasons for this is so that we don't pollute the interface of our control with unexpected or non-public data.

The substitute object

If we have no bound object, we can create a substitute one with a call to bpmext.ui.substituteObject().

The substitute config options

If we have no bound configuration option, we can create a substitute one with a call to bpmext.ui.substituteConfigOption().

For example:

bpmext.ui.substituteConfigOption(this, "color", "black");

Event handling

To register an event handler, we can call bpmext.ui.registerEventHandlingFunction().

For example:

bpmext.ui.registerEventHandlingFunction(this, "onclickEvent");

The name of the event must be a configuration option of type string. Looking at the previous example, we would need a configuration option called "onclickEvent". What this will hold at design time is a fragment of JavaScript code which will be evaluated when the event is fired.

The way we fire an event is to call bpmext.ui.executeEventHandlingFunction(this, "onclickEvent").

Formula handling

To register for formula handling, we can call bpmext.ui.setupFormulaTriggeredUpdates().

The signature of this function is

bpmext.ui.setupFromulaTriggeredUpdates(view, updateFn, resultFn)

The updateFn function is invoked when the value of the formula associated with the control needs to be updated.

The resultFn is a function that is invoked that must return a value. This value is what is returned when we use the scripting shortcut "@{<name>}". The semantics of this is to return the current value of the control as it can be used in other formulaic expressions.

When the value of our control changes we need to inform other controls that formulas in use that refer to our value need to be updated. We do this through a call to "bpmext.ui.broadcastExpressionTrigger()".


  • It appears that the formula is obtained from a configuration option called "expression". Is that correct?

Documentation generation

The source should contain JsDoc markup for automatic generation of documentation.

Each public method should have a JsDoc comment of the following format:

* @instance
* @memberof
* @method
* @desc
* @returns

See also:


  • addEventSubscription(eventName, callback, view, persistent)

  • alert(topic)

  • eventSubscriptionExists(eventName, view)

  • executeEventHandlingFunction(view, eventName)

  • forEachViewSibling(view, callback)

  • getChildContainers(view, deep)

  • getChildViews(view, deep)

  • getCoachNGViewPath(view)

  • getContainer(viewPath, fromView)

  • getContainerPath(view)

  • getEffectiveVisibility(view)

  • getEventHandlingFunction(view, eventName)

  • getFunction(functionName, fromView)

  • getFunctionContext(functionName, fromView)

  • getInvalidViews(view)

  • getNearestValidationContainer()

  • getOption(view, optionName, defaultValue)

  • getRequiredViews(onlyEmpty, fromView)

  • getValidationContainers()

  • getView(viewPath, fromView)

  • getViewData(viewPath, fromView)

  • getViewPath(getViewPath)

  • getViewValidationErrors()

  • isViewExplicitlyLoaded(view)

  • loadContainer(view)

  • loadView(view)

  • makeUniqueId(prefix)(prefix)

  • popValidationContainer()

  • publishEvent(eventName, payload, persistent)

  • pushValidationContainer()

  • registerEventHandlingFunction(view, eventName)

  • removeEventSubscription(eventName, view)

  • removeViewValidationError()

  • setupFormulaTrigeredUpdates()

  • setViewData(data, viewPath, fromView)

  • setViewEnabled(enabled, required)

  • substituteConfigOption(view, propertyName, defVal)

  • substituteObject(view, type, propertyName, defVal)

  • unloadContainer(view)

  • unloadView(view)

  • updateViewValidationState()

addEventSubscription(eventName, callback, view, persistent) Add an event subscription to a view
alert(topic) Broadcasts an alert withe the parameters specified
eventSubscriptionExists(eventName, view) Determine if a view is subscribing to an event.
executeEventHandlingFunction(view, eventName) Executes an event handling function.
forEachViewSibling(view, callback) Convenience iterator function.
getChildContainers(view, deep) Will return a list of all child container views of the specified view
getChildViews(view, deep) Will return a list of all child views of the specified view
getContainer(viewPath, fromView) Retrieves the view corresponding to the path specified
getContainerPath(view) Returns the absolute path of the view/section
getEffectiveVisibility(view) returns the actual visibility of a view.
getEventHandlingFunction(view, eventName) Retrieve an event handling function.
getFunction(functionName, fromView)
getFunctionContext(functionName, fromView)
getNearestValidationContainer() Gets the top view on the validation stack
getOption(view, optionName, defaultValue) Retrieves the configuration option value
getRequiredViews(onlyEmpty, fromView)
getValidationContainers() Returns the validation container stack
getView(viewPath, fromView) Retrieves the view corresponding to the path specified
getViewData(viewPath, fromView) Retrieves the bound data for the view corresponding to the path specified.
getViewPath(getViewPath) Returns the absolute path of the view
getViewValidationErrors() Returns the validation errors for the specified view
isViewExplicitlyLoaded(view) Returns an indication of whether or not this view has been explicitly loaded
makeUniqueId(prefix) Returns a unique ID to be used on the currently-displayed page.
popValidationContainer() Pop the specified view from the validation container stack
publishEvent(eventName, payload, persistent) Publish an event.
pushValidationContainer() Push the specified view into the validation container stack
registerEventHandlingFunction(view, eventName) Register an event handling function.
removeEventSubscription(eventName, view) Removes the specified event from the list of subscribed events for the specified view
removeViewValidationError() Removes the error on the specified id in the specified view
setupFormulaTrigeredUpdates() Registers formula triggers for the specified view
setViewData(data, viewPath, fromView) Sets the bound data for the view corresponding to the path specified
setViewEnabled(enabled, required) Enable/disable this view/control
substituteConfigOption(view, propertyName, defVal)
substituteObject(view, type, propertyName, defVal)
unloadContainer(view) Deregisters a section Coach View (but not a regular view) from the view tree.
unloadView(view) Deregisters a Coach View (but not a section) from the view tree.
updateViewValidationState() Gets the top view on the validation stack

View Navigation

View navigation is about finding or traversing views.

  • forEachViewSibling(view, callback)

  • getChildContainers(view, deep)

  • getChildViews(view, deep) - Get an array of child views (not containers). If the deep value is true, we will return recursively otherwise just the immediate children are returned.

  • getView(viewPath, fromView)

  • getViewPath(getViewPath)

  • <view>.context.viewid

See also:


These methods are added to each view under the "ui" namespace.

  • addEventSubscription(eventName, callback)

  • get(path, index)

  • getAncestor(name, literal)

  • getCount(viewPath)

  • getIndex()

  • getAbsoluteName() - Return a string representation that can be used to address the view.

  • getOption(optionName, defVal)

  • getParent(literal) - Return the single view that is the parent of the called view. If literal is true then we will return the CoachNG parent, otherwise we return the first non-decorative parent. This may also return undefined if there is no parent.

  • getSibling(name)

  • invoke(functionName, args …)

  • getChild(name, index)

  • isSubscribingToEvent(eventName)

  • publishEvent(eventName, payload)

  • removeEventSubscription(eventName)

Creating a new custom Coach View

Here is the recipe for creating a new custom Coach View that matches the pattern followed by SPARK UI.

Imagine our new Coach View is going to be called "Xyz".

Create a JavaScript source file called "Xyz.js". Use the following as a template:

myControl_xyz = function (bpmext)
   // Store any instance specific data within this object.  Data stored in here will
   // be assured to be private and unique to this instance of the coach view and
   // not visible to others.
   this._instance = {

   if (!this.constructor.prototype._proto)
      this.constructor.prototype._proto =
         _handleVisibility : function (view)
            var visibility = bpmext.ui.getEffectiveVisibility(view);

            view.context.setDisplay(visibility != "NONE");
            view.context.setVisibility(visibility != "HIDDEN");
         _myFunction : function(view) { //internal function
            // My code goes here.
      this.constructor.prototype.myFunction = function () {
         //publicly available method calls internal function

      this.constructor.prototype.getType = function ()
         return "xyz.1";
      this.constructor.prototype.load = function ()
            var opts = this.context.options;
            //default configuration values
            	bpmext.ui.substituteConfigOption(this, "myConfig", <defaultValue>);
            var mdt = opts._metadata;
         catch (e)

      this.constructor.prototype.view = function ()
         catch (e)


      this.constructor.prototype.change = function (event)
            if (event.type == "config")
               switch (
                  case "_metadata.visibility":
         catch (e)

      this.constructor.prototype.validate = function (event) {

      this.constructor.prototype.collaboration = function (event) {

      this.constructor.prototype.unload = function ()

Next, add this file to your toolkit as a managed Web file. Now we can create the Coach View. In the Included Scripts section, add a reference to the newly added Web file.

In the AMD dependendencies, add:

com.salientprocess.bpm.views/bpmext -> bpmext

In the "Inline Javascript" add:, bpmext);

SPARK UI References

DOM Programming

While DOM programming is a general programming discipline in its own right, we will cover here some of the notes I have found useful when working in this area.

Creating a new element.

var newElement = document.createElement("<tagName>");

Adding an element to the DOM Tree


Finding the first matching node

var node = element.querySelector("<CSS Selector>");

Finding all the matching nodes

var nodeList = element.querySelectorAll("<CSS Selector>");

Get the parent of a node

var parent = element.parentNode;
var parent = element.patentElement;

The return is null if we have no parent.

Adding text to a node

We can create a text node using <element>.createTextNode("<text>") and then add that node as a child of our parent node.

var newTextNode = document.createTextNode("Hello!");

Another setter for text is to assign to the textContent property. For example:

parent.textContent = "Hello!";

Yet another option is innerText.

SPARK UI Cheat Sheet

No Comments
Back to top