Contents


Branding and customizing the coach controls in IBM Business Process Manager

Creating your own controls and incorporating advanced features in controls

Comments

IBM® Business Process Manager (BPM) includes vibrant and configurable controls for coaches, which you use to build to build user interfaces (UI) that your process participants use to interact with a service. Occasionally, developers might need to create additional components to extend functionality. This tutorial looks at the available options for beginner-to-novice level developers for building new controls and incorporating advanced features into the controls. More advanced topics are discussed, which require an understanding of Exposed Process Variables and the IBM BPM cascading style sheet (CSS) styles. The same techniques apply to coaches for both heritage human services for client-side human services. Coaches for client-side human services also contain additional options, as described in the IBM BPM 8.5.5 Responsive Coaches video on the IBM Business Process Manager Developer Center and in the Designing responsive coaches in IBM Business Process Manager 8.5.5 blog entry.

The techniques in this tutorial are functional in IBM BPM V8.X environments. You should have a basic understanding of HTML, JavaScript, IBM BPM, and the coaches framework.

When you create controls for an IBM BPM application, it is important to consider the time-to-output requirement. The main purpose of the business application is to model business processes. For this reason, control additions should be a secondary requirement to process implementation. There are other toolkits in the Smarter Process Community on IBM Bluemix DevOps Services that provide additional control sets, for example, bpm-CoachViewExamples. Be advised that because they are community assets, some of the controls might act unexpectedly or not work on some versions of IBM BPM.

IBM BPM comes with different UI components that allow developers to create coaches according to an organization's needs. These stock components are built on the Dojo UI framework, a library of JavaScript-driven controls. For manipulating the stock control schemes, such as colors, see Leveraging the IBM BPM Coach Framework in Your Organization, an IBM Redbooks publication. However, for some scenarios, the control capabilities in the IBM BPM coach framework might not meet an organization's needs.

Organizations that require mobile-focused controls or controls that work better for users with smaller screen sizes (for example, tablets), creating a custom control might be the answer. If the organization requires a UI control that is not included in the existing stock controls, a custom control might also be the answer. There are an abundance of existing libraries that can be created in the IBM BPM product. Depending on the product version, the Dojo library itself includes many controls that are not built into IBM BPM but that developers can create in IBM BPM.

Evaluating UI frameworks

When looking at UI libraries, it is important to understand the breadth of desired components. Does your organization require only a single component or several components? Several components might be easier to develop from a full library. Does the proposed library include a multitude of control types that developers might need to use later? Importing the entire library might make this process easier. Another important consideration for working with third-party user interfaces outside of IBM BPM is the support you might need. Does IBM have any affiliation with the third-party producer so that you can get support if needed from IBM? Is the library undergoing active development, or is it no longer in use?

A major consideration, especially with the widening use of mobile devices, is the availability of the library on a mobile device. Does the library work on mobile devices? Does it provide scaling to screen size? A common library to consider is jQuery, which requires additional files to be loaded on top of IBM BPM. Will this affect how your organization uses IBM BPM?

Extending IBM BPM coaches with existing libraries

One of the simplest ways to introduce new UI controls to an application is through the Dojo library. The IBM BPM product ships with Dojo, and the existing controls are built using this library, which means that you do not need to include additional files or attachments. Another important consideration is the widespread availability of documentation on Dojo. Using a search engine, it is relatively simple to find the required source code and build the component in IBM BPM.

Creating a custom control in an IBM BPM coach

The following example looks at the requirements for building the Dojo slider in IBM BPM. See the Dojo library documentation at dijit/form/HorizontalSlider to easily recreate the code in IBM BPM.

For example, complete the following steps to create a custom slider control in an IBM BPM coach:

  1. Create a coach view in your process application or toolkit by clicking the add button for User Interface and selecting Coach View. Assign a name that is relevant to the control type. For example, name the coach view for a slider control Slider. The Layout tab opens automatically, as shown in the Slider coach view example in Figure 1.
    Figure 1. Example Slider coach view
    Screen                             capture of an example coach view named Slider
    Screen capture of an example coach view named Slider
  2. On the Behavior tab of the coach view, place the JavaScript for the slider (according to the Dojo documentation) in the code window for a load event handler, as shown in Figure 2.
    Figure 2. The code window for a load event handler
    Screen capture of the code window for a load                     event handler
    Screen capture of the code window for a load event handler
  3. Open the palette on the coach view and place a Custom HTML block on the diagram. Copy the HTML from the Dojo slider documentation and paste it in the HTML block, as shown in Figure 3.
    Figure 3. The Custom HTML block
    Screen capture of a custom HTML block
    Screen capture of a custom HTML block
  4. Open a new human service and create a coach on the palette. Drag the slider coach view onto the coach, and then run the human service. You have now created a custom slider control, as shown in Figure 4. The number field is included as the input tag.
    Figure 4. Example custom slider control
    Example custom slider control
    Example custom slider control

Binding the coach view to data from the human service

After creating the slider, look at how to bind the coach view to the data from the human service, which allows you to interact with it. Binding the coach view to the human service data requires some adjustment to the JavaScript used and requires binding variables to the coach view. First consider what the configuration variables are and what the bound variable is. For the following example, the bound variable is an integer, which is shown as a decimal, and there are several configurations (min, max, and steps), each an integer. For other custom coach views, create the variables and configurations appropriately.

For example, complete the following steps to bind the coach view to data from the human service:

  1. Open the slider coach view and create a business variable for the binding using the integer type for the end value to bind to. Create configuration variables for the min, max, and steps each of type integer, as shown in Figure 5.
    Figure 5. Example business variable
    Example business variable
  2. Open the Behavior tab, and for the load, add the configurations and the bound variable to the slider. Call the variables and use defaults. In the following example, the very last value for each of the variables is the default value. This is important, because if a variable is not provided to the coach view, the slider fails without the default set.var boundValue = this.context.binding && this.context.binding.get("value") ? this.context.binding.get("value") : 0;
  3. To update the bound variable based on changes by the end user at run time, add one more line of code like the following example. Notice the copy of the handle, which allows constant updating of the value.
            onChange: function(value){
                //dom.byId("sliderValue").value = value;
                boundValue = value;
                console.log("change")
                _this.context.binding.set("value",boundValue);
            }
  4. Open your human service with the slider and create a private variable of the integer type. Bind the variable to an integer control on the diagram, and then bind it to the slider control. Feel free to provide configuration inputs to the slider.
  5. Run the human service and move the slider. The integer box should update with the correct value. Note that the slider does not allow a number entry because the box is only an output.

See the following example for the complete code:

//console.log("1");
var boundValue = this.context.binding && this.context.binding.get("value") ? this.context.binding.get("value") : 0;
//console.log("2");
var min = this.context.options && this.context.options.min ? this.context.options.min.get("value") : 0;
//console.log("3");
var max = this.context.options && this.context.options.max ? this.context.options.max.get("value") : 10;
var step = this.context.options && this.context.options.step ? this.context.options.step.get("value") : 1;
var style = this.context.options && this.context.options.style ? this.context.options.style.get("value") : "width:300px;";
var id = this.context.viewid;
//console.log(id)
var slideDiv = document.getElementById("start");
slideDiv.setAttribute("id", id);
//console.log(slideDiv);
var _this = this
//console.log("2");
require([
    "dojo/dom", // for inserting value in TextBox example
    "dojo/parser", // parser because of TextBox decoration
    "dijit/form/HorizontalSlider",
    "dijit/form/TextBox" // this we only include to make an example with TextBox
], function(dom, parser, HorizontalSlider, TextBox){
	//console.log(id);
    parser.parse();
    //console.log("inside"+_slideDiv);
    //var _new = _bound
    var slider = new HorizontalSlider({
        name: "slider",
        value: boundValue,
        minimum: min,
        maximum: max,
        intermediateChanges: true,
        style: style,
        discreteValues: step,
        onChange: function(value){
            //dom.byId("sliderValue").value = value;
            boundValue = value;
            console.log("change")
            _this.context.binding.set("value",boundValue);
        }
    }, id).startup();
});

Control ID

There is one last piece to consider: the control ID. Looking through the slider code, notice the reference to the view ID. This reference provides the required unique widget ID. To see this issue in action, drag an additional slider onto the human service and run the service, as shown in the previous example.

Without the unique ID, you see a blank browser window and receive an error message about an ID error in the browser console that is accessed either through Firebug or similar browser tools. This error is because HTML IDs must be unique, meaning that two sliders with the implementation cannot exist on the coach. To address this issue, IBM BPM has built-in behavior that provides the view ID, accessible as a coach view attribute, which easily allows developers to create unique IDs from the view ID.

Use the following code in your coach view load behavior to set the ID of the control to a unique value:

var id = this.context.viewid;

Extending IBM BPM coaches with Asynchronous Module Definition (AMD) modules

AMD modules are a way that developers can quickly load a library widget and reference it in the coach view. The examples in this tutorial now switch to using the Dojo dialog control. In this example you load the AMD module for the Dojo dialog control.

Using the code structure from the Dojo documentation, you can copy and adjust it in the load behavior of the coach view. In addition, for this example, you want to have a button that can submit to the next task. For this button, the example uses the event firing behavior.

Complete the following steps to add AMDs to the coach view, which allows better loads.

  1. Open the Button coach view from the Coaches toolkit in Process Designer and copy the Button coach view into your application. Rename the coach view Dialog Button.
  2. Add an AMD dependency, as shown in Figure 6.
    Figure 6. Example of adding an AMD dependency
    Example of adding an AMD dependency
    Example of adding an AMD dependency
  3. Open the HTML Block on the coach view palette and use the following code to define the button and dialog HTML.
    <!-- This div was added to allow the dialog box to open >→
    <div data-dojo-type="dijit/Dialog" data-dojo-id="myDialog">
    </div>
    <button> type="button" class>="BPMButton BPMButtonBorder" ></button>
  4. Provide configuration options, as shown in Figure 7.
    Figure 7. Example configuration options
    Example configuration options
  5. Put the Dialog Button coach view on a coach, and you're done. The AMD loads the needed Dojo components more quickly than coding with dojo.require would.
  6. Provide values for the configuration options, and put the coach view on a coach, as shown in Figure 8.
    Figure 8. Example coach view
    Example coach view
    Example coach view
  7. Run the coach, and click the button. A dialog window should open.

    Dojo has a number of advantages for IBM BPM developers. Most significantly, Dojo is included with IBM BPM, meaning developers are able to use it without having to download additional files.

See the following code example for the complete code:

var baseTextDirection = this.context.options._metadata.baseTextDirection && this.context.options._metadata.baseTextDirection.get("value") ? this.context.options._metadata.baseTextDirection.get("value") : utilities.BiDi.BASE_TEXT_DIRECTION._default;
var generalPrefTextDirection = this.context.bpm.system.baseTextDirection;
 
           //Gets the value input for the text content and labels          
var innerText = this.context.options.innerText && this.context.options.innerText.get("value") ? this.context.options.innerText.get("value") : "";
var title = this.context.options.title && this.context.options.title.get("value") ? this.context.options.title.get("value") : "";
var confirmLabel = this.context.options.confirmLabel && this.context.options.confirmLabel.get("value") ? this.context.options.confirmLabel.get("value") : "Submit";
var cancelLabel = this.context.options.cancelLabel && this.context.options.cancelLabel.get("value") ? this.context.options.cancelLabel.get("value") : "Cancel";
var button = this.context.element.getElementsByTagName("button")[0];

                //Adds the buttons to the dialog needs corrected spacing and labels
innerText = innerText + "<div class='dijitDialogPaneActionBar'><div style='display:inline-block;padding:5px'><button id='ok' class='BPMButton BPMBorder' type='button'>" +confirmLabel+ "</button>"
	 +"</div><div style='display:inline-block;padding:5px'><button id='cancel' class='BPMButton BPMBorder' type='button'>" +cancelLabel+ "</button></div></div>";
var visibility = utilities.handleVisibility(this.context, null, null, [button]);
if (visibility != "NONE") {
   if (this.context.options._metadata.label && this.context.options._metadata.label.get("value") != "") {
   button.innerHTML = this.context.htmlEscape(this.context.options._metadata.label.get("value"));
   utilities.BiDi.applyTextDir(button, button.innerHTML, baseTextDirection, generalPrefTextDirection);
   } else {
	 button.innerHTML = "&nbsp;";
 }
 if (this.context.options._metadata.helpText && this.context.options._metadata.helpText.get("value") != "") {
 button.title = this.context.options._metadata.helpText.get("value");
 }
 button.onmousedown = function() {
 domClass.add(this, "BPMButton-down");
 };
 button.onmouseout = button.onmouseup = function() {
	 domClass.remove(this, "BPMButton-down");
     };
   var _this = this;
     button.onclick = function() {
	if (this.disabled == false) {
	 var context = _this.context;
	 if (context.binding) {
	         context.binding.set("value", true);
	 }
	 var _button = this;
	 //Sets the inner content and title
	 myDialog.set("content",innerText);
	 myDialog.set("title",title);

	 //Starts the dialog when the button is clicked
	 myDialog.show();
	 
	 //Corrects the styling on the title bar
	 if(document.getElementsByClassName("dijitDialogTitleBar")[0]){
	 document.getElementsByClassName("dijitDialogTitleBar")[0].className = "BPMSectionHeader box blue"}
	 
	 //Finds the submit button
	 var submit = document.getElementById("ok");
	 //Trigger for completing task is placed on the dialog button instead of the triggering button
	 submit.onclick = function() {
	 context.trigger(function() {_button.disabled = false; domClass.remove(_button, "BPMButton-disabled");});
	 }
	 //This finds the cancel button and triggers the dialog to close when clicked
	 var cancel = document.getElementById("cancel");
	  cancel.onclick = function() {
           myDialog.hide();           
	 }
 }
 }
 this.updateStyle();
            };

Extending IBM BPM coaches with third-party libraries

Despite the extensive number of elements that the stock IBM BPM library contains, there might be situations that require additional components. A prominent library in the UI world that could meet this need is Foundation. The Foundation library includes a number of different controls that are not included in IBM BPM and are particularly relevant to mobile devices. Foundation is built on jQuery, which also opens additional functionality to developers. However, whether the library is Foundation, Bootstrap, jQuery, or others, the steps are relatively similar.

Importing files

One of the first considerations involves the intricate way that IBM BPM loads files attached to coach views. Looking at the Foundation library, the coach needs to load the required JavaScript files in a particular order to ensure that the components function. In the download of the UI library, the files that the coach must load are included as separate JavaScript files. For more information, see the Foundation website.

An important change that you must make is assembling a single JavaScript file with all of the required JavaScript files in the load order dictated by Foundation. This means copying and pasting all of the required JavaScript into one file in the correct order. If jQuery is used by the desired library, then jQuery is included in the file also. This step is absolutely crucial. If it is not correct, you might find inconsistent results, or the coach might not work at all. After compiling the file, you can add the file in the Process Designer as a web file and then attach the file to the coach view as needed. In Figure 9, all three JavaScript files are in the foundation.min.js file in the correct order.

Figure 9. JavaScript files in the foundation.min.js file
JavaScript files                 in the foundation.min.js file

Configuring the system

Another important consideration with mobile-ready libraries is the need to set the viewport so that the page can scale accordingly. A IBM BPM coach does not do this automatically, so you must set the viewport in the coach view like the following example:

var meta = document.createElement('meta');
meta.name = "viewport";
meta.content = "width=device-width, initial-scale=1.0";
document.getElementsByTagName('head')[0].appendChild(meta);

When importing additional libraries, you might face issues with conflicting CSS classes. In some cases, IBM BPM adds additional classes to components, or components have the same names between libraries. The easiest way to counteract these significant issues is to remove the stock style sheets. Use the following code:

domAttr.remove(query("body")[0],"class","claro");
domAttr.remove(query("html")[0],"class","dj_gecko");
domAttr.remove(query("html")[0],"class","dj_contentbox");
domAttr.remove(query("html")[0],"class","dj_ff24");

In addition, you might be required to remove all references to the stock CSS files. Remove the document elements that reference the CSS files. The main culprit is the coach_ng.css file.

Building the third-party components

After importing the correct files and configuring the system, the components can be built in the same way as the previously described Dojo components, which means using coach views correctly. If jQuery is a part of the included file set, you can call jQuery functions from within the event handlers of the coach view.

Extending IBM BPM coaches with the REST protocol

Another important consideration is the inclusion of the REST protocol. REST has become a standard feature with IBM BPM, and leveraging REST allows for a broader range of stock functions and easier use of these functions in UI controls. For updated usage of Dojo REST, see thedojo/request/xhr Dojo Toolkit documentation.

Implementing this method with timers allows developers to rapidly create functions and displays that might need to be refreshed frequently, like the task list. Using REST, you can easily extend the Foundation off-canvas menu to be used as a mobile-ready Process Portal, simply by adding a timer function.

Using the Dojo XHR Request, you can easily gather information and use it on the page. The following code example contains code you can use to retrieve the task stream for a particular task and then inject it into the page. However, as explained previously, you would probably want to declare an AMD dependency rather than using dojo.require in the script. REST requests can easily be performed from within the event handlers of a coach view or from within a function defined in an included script.

Code example

function taskContain(){
require(["dojo/request/xhr"], function(xhr){
  var context = _this.context;
  var url = "/rest/bpm/wle/v1/search/query";
  xhr(url, {
    handleAs: "json",
    query: {
    condition:"instanceStatus|Active",
    organization:"byInstance",
    run:true,
    shared:false,
    filterByCurrentUser:true
    },
    headers: { 'Content-Type': 'application/json', 'Accept':'application/json' },
    method:"PUT"
  }).then(function(data){
    taskContainer.innerHTML = "";
    for(var i=0;i<data.data.data.length;i++){
        if(data.data.data[i].taskStatus!="Closed"){
        console.log("found one");
        var subject = data.data.data[i].taskSubject;
        var taskId = data.data.data[i].taskId;
        };
        };
  }, function(err){
    // Handle the error condition
  }, function(evt){
    // Handle a progress event from the request if the
    // browser supports XHR2
  });
});}

Conclusion

This tutorial examined different ways to create custom coach controls in IBM BPM. It explained the Dojo framework included in IBM BPM and how to develop components without having to include additional packages. This tutorial also examined how to use third-party frameworks such as Foundation to create new mobile ready components. Finally, the tutorial showed how to leverage REST to provide required functionality and mobile readiness.

Acknowledgements

The author would like to thank James Carr for his review and contributions to this tutorial.


Downloadable resources


Related topics


Comments

Sign in or register to add and subscribe to comments.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Middleware
ArticleID=1009222
ArticleTitle=Branding and customizing the coach controls in IBM Business Process Manager
publish-date=06242015