转载

在 IBM Business Process Manager 中对 Coach 控件进行品牌化和定制

简介

IBM® Business Process Manager (BPM) 包括一些充满活力的、可配置的 Coach 控件,您可以使用它们构建用户界面 (UI),流程参与者将使用这些界面与服务进行交互。有时,开发人员可能需要创建额外的组件来扩展功能。本教程将重点介绍适用于新手级开发人员的可用选项,帮助他们构建新的控件,并将高级特性集成到控件中。本文还会讨论更高级的话题,这要求对 Exposed Process Variables 和 IBM BPM 级联样式表 (CSS) 样式有一定的理解。相同的技术也适用于客户端人性化服务和传统人性化服务的 Coach。客户端人性化服务的 Coach 还包含额外的选项,如在 IBM Business Process Manager 开发人员中心上的 IBM BPM 8.5.5 响应式 Coach 视频 和 在 IBM Business Process Manager 8.5.5 中设计响应式 Coach 中所述。

尝试使用 Workflow 服务

创建长时间运行的有状态工作流,利用 来自 Bluemix 的 Workflow 服务 中的同步或异步事件驱动交互来协调任务和服务。免费试用该服务!

本教程中的技术能够在 IBM BPM V8.x 环境中发挥作用。读者应该对 HTML、IBM BPM 和 Coach 框架有基本的了解。

在为 IBM BPM 应用程序创建控件时,重要的是要考虑到输出时间的要求。业务应用程序的主要目的是对业务流程建模。因此,控件添加应该是流程实现的次要要求。IBM Bluemix DevOps Services 上的 Smarter Process Community 中的其他工具包也提供了额外的控件集,例如, bpm-CoachViewExamples 。请注意,因为它们是社区资产,有些控件在某些版本的 IBM BPM 中可能有意外的行为,或者无法工作。

IBM BPM 带有的多种 UI 组件让开发人员可以根据组织的要求创建 Coach。这些常用的组件都建立在 Dojo UI 框架上,该框架是一个 JavaScript 驱动的控件库。有关操纵常备控件方案(如颜色)的更多信息,请参阅 IBM 红皮书《在组织中利用 IBM BPM Coach Framework》 。不过,在某些场景中,IBM BPM Coach 框架中的控件功能可能无法满足组织的要求。

如果组织需要以移动为重点的控件,或为使用较小尺寸屏幕(例如,平板电脑)的用户带来效果更好的控件,那么组织可能会创建自定义控件。如果组织需要的 UI 控件没有包括在现有的常备控件中,那么组织可能也会创建自定义控件。在 IBM BPM 产品中可以创建大量现有的库。根据不同的产品版本,Dojo 库本身可能包括未内置到 IBM BPM 的许多控件,但开发人员可以在 IBM BPM 中创建它们。

回页首

评估 UI 框架

在查看 UI 库时,重要的是要了解所需组件的广度(breadth)。您的组织是否只需要一个组件或多个组件?如果有完整的库,可能会更容易开发多个组件。所建议的库是否包括开发人员可能在以后需要使用的多种控件类型?导入整个库可能会使这个流程更容易完成。使用 IBM BPM 之外的第三方用户界面有另一个重要的考虑因素:您可能需要的支持。IBM 与第三方生产商是否有任何隶属关系,这样在需要 IBM 支持的时候就可以获得支持?该库是否正处于活跃开发中,或者是否已不再使用它?

一个主要的考虑因素(特别是与移动设备的更广泛使用有关的情况下)是库在移动设备上的可用性。该库在移动设备上是否正常工作?它是否能按屏幕尺寸缩放?可以考虑的公用库是 jQuery,这需要在 IBM BPM 上加载其他文件。这是否会影响您的组织如何使用 IBM BPM?

回页首

利用现有的库扩展 IBM BPM Coach

通过 Dojo 库将新的 UI 控件引入应用程序是最简单的方法。IBM BPM 产品附带 Dojo,而现有的控件是使用此库构建的,这意味着您不必包括其他文件或附件。另一个重要的考虑是 Dojo 文档的广泛可用性。使用搜索引擎,查找所需的源代码和在 IBM BPM 中构建组件会相对简单一些。

在 IBM BPM Coach 中创建自定义控件

下面的示例着眼于在 IBM BPM 中构建 Dojo 滑块的需求。请在 dijit/form/HorizontalSlider 参阅 Dojo 库文档,在 IBM BPM 中轻松地重新创建代码。

例如,完成以下步骤,在 IBM BPM Coach 中创建自定义滑块控件:

  1. 单击 User Interface 并选中 Coach View ,在流程应用程序中创建一个 Coach 视图或工具包。指定一个与控件类型相关的名称。例如,将一个滑块控件的 Coach 视图命名为 Slider 。Layout 选项卡会自动打开,如图 1 中的 Slider Coach 视图示例。

    图 1. 示例 Slider Coach 视图

    在 IBM Business Process Manager 中对 Coach 控件进行品牌化和定制
  2. 在 Coach 视图 的 Behavior 选项卡中,将滑块的 JavaScript(根据 Dojo 文档)放进加载事件处理程序的代码窗口中,如图 2 所示。

    图 2. 加载事件处理程序的代码窗口

    在 IBM Business Process Manager 中对 Coach 控件进行品牌化和定制

    点击查看大图

    关闭 [x]

    图 2. 加载事件处理程序的代码窗口

    在 IBM Business Process Manager 中对 Coach 控件进行品牌化和定制

  3. 打开 Coach 视图上的调色板,并将 Custom HTML 块放在图上。从 Dojo 滑块文档复制 HTML,并将它粘贴到 HTML 块中,如图 3 所示。

    图 3. Custom HTML 块

    在 IBM Business Process Manager 中对 Coach 控件进行品牌化和定制
  4. 在 Coach 上打开一个新的人性化服务,并创建调色板。将滑块 Coach 视图拖动到 Coach,然后运行人性化服务。现在,您已经创建了一个自定义的滑块控件,如图 4 所示。数字字段作为输入标签。

    图 4. 自定义的滑块控件示例

    在 IBM Business Process Manager 中对 Coach 控件进行品牌化和定制

将 Coach 视图绑定到人性化服务的数据

在创建滑块后,了解如何将 Coach 视图绑定到人性化服务的数据,该服务允许您与它进行交互。将 Coach 视图绑定到人性化服务数据需要对所使用的 JavaScript 进行一些调整,并需要将变量绑定到将 Coach 视图。首先考虑的配置变量是什么,以及绑定变量是什么。对于下面的示例,绑定变量是整数,它被表示为一个十进制数字,并有几种配置(最小值、最大值和步长),每一个变量都是整数。对于其他自定义 Coach 视图,要相应地创建变量和配置。

例如,完成如下步骤,将 Coach 视图绑定到人性化服务数据:

  1. 打开滑块 Coach 视图并为绑定创建业务变量,对绑定的最终值使用 integer 类型。创建最小值、最大值和步长配置变量,每一个变量的类型都是 integer,如图 5 所示。

    图 5. 业务变量示例

    在 IBM Business Process Manager 中对 Coach 控件进行品牌化和定制
  2. 打开 Behavior 选项卡,为了实现加载,将配置和绑定变量添加到滑块。调用变量,并使用默认值。在下面的示例中,每个变量的最后一个值都是默认值。这一点很重要,因为如果没有向 Coach 视图提供一个变量,滑块会失败,原因是没有默认的 set.var boundValue = this.context.binding && this.context.binding.get("value") ? this.context.binding.get( "value") :0;
  3. 为了根据最终用户在运行时所做的更改来更新绑定变量,增加类似下面示例中的一行代码。注意句柄的复制,它实现了值的不断更新。
    onChange:function(value){             //dom.byId("sliderValue").value = value;             boundValue = value;             console.log("change")             _this.context.binding.set("value",boundValue);         }
  4. 打开有滑块的人性化服务,并创建一个 integer 类型的私有变量。将变量绑定到图上的一个 integer 控件,然后将其绑定到滑块控件。向滑块随意提供一些配置输入。
  5. 运行人性化服务并移动滑块。integer 方框应更新为正确的值。请注意,滑块不允许输入数字,因为该框只用于输出。

请看下面的完整代码示例:

点击查看代码清单

关闭 [x]

//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(); }); 

控件 ID

还有最后一个考虑因素:控件 ID。仔细查看滑块代码,注意对视图 ID 的引用。该引用提供了所需的惟一部件 ID。为了实际了解这个问题,可以将另一个滑块拖到人性化服务,并运行服务,如前面的示例所示。

如果没有惟一的 ID,则会看到一个空白的浏览器窗口,并在通过 Firebug 或类似浏览器工具访问的浏览器控制台中收到有关 ID 错误的错误信息。这个错误是因为 HTML ID 必须是惟一的,这意味着在 Coach 上不能包含两个滑块。为了解决这个问题,IBM BPM 有内置行为可以提供视图 ID,可以作为一个 Coach 视图属性被访问,这很容易让开发人员能够从视图 ID 创建惟一的 ID。

在以下 Coach 视图加载行为中使用下面的代码,将控件的 ID 设置为惟一值:

var id = this.context.viewid;

回页首

利用 Asynchronous Module Definition (AMD) 模块扩展 IBM BPM Coach

AMD 模块是让开发人员能够快速加载库部件并在 Coach 视图中引用它的方式。本教程中的示例现在切换到使用 Dojo 对话框控件。在这个示例中,加载 Dojo 对话框控件的 AMD 模块。

使用来自 Dojo 文档的代码结构,您可以复制它并在 Coach 视图的加载行为中对其进行调整。此外,在这个示例中,您希望有一个按钮,可以提交到下一个任务。对于此按钮,该示例使用事件触发的行为。

完成以下步骤,将 AMD 添加到 Coach 视图,它可以实现更好的加载。

  1. 在 Process Designer 中从 Coaches 工具包打开 Button Coach 视图,将 Button Coach 视图复制到您的应用程序中。将这个 Coach 视图重命名为 Dialog Button
  2. 添加一个 AMD 依赖关系,如图 6 所示。

    图 6. 添加 AMD 依赖关系的示例

    在 IBM Business Process Manager 中对 Coach 控件进行品牌化和定制
  3. 在 Coach 视图调色板上打开 HTML Block,使用下面的代码来定义按钮和对话框的 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. 提供配置选项,如图 7 所示。

    图 7. 配置选项示例

    在 IBM Business Process Manager 中对 Coach 控件进行品牌化和定制
  5. Dialog Button Coach 视图放在一个 Coach 上,大功告成。AMD 加载所需 Dojo 组件的速度比使用 dojo.require 编写代码实现此操作的速度还要快。
  6. 为配置选项提供值,并将 Coach 视图放在一个 Coach 上,如图 8 所示。

    图 8. 示例 Coach 视图

    在 IBM Business Process Manager 中对 Coach 控件进行品牌化和定制
  7. 运行 Coach,并单击按钮。一个对话框窗口将会打开。

    对于 IBM BPM 开发人员来说,Dojo 存在一些优势。最明显的优势是,IBM BPM 包含了 Dojo,这意味着开发人员无需下载其他文件就能使用它。

请参阅下面的完整代码示例:

点击查看代码清单

关闭 [x]

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 = " ";  }  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();             };

回页首

利用第三方库扩展 IBM BPM Coach

尽管常备的 IBM BPM 库中包含大量元素,但在某些情况下,可能需要额外的组件。UI 世界中有一个重要的库能够满足这种需求,这个库就是 Foundation。Foundation 库包括许多 IBM BPM 中没有的不同控件,并且与移动设备有密切的关系。Foundation 构建于 jQuery 之上,后者也为开发人员带来了额外的功能。但是,不论是 Foundation、Bootstrap、jQuery 库,还是其他的库,步骤都比较相似。

导入文件

首先考虑的因素之一涉及到 IBM BPM 加载 Coach 视图所附文件的复杂方式。看看 Foundation 库,Coach 需要按某个特定的顺序加载所需的 JavaScript 文件,以确保组件正常工作。在下载 UI 库时,Coach 必须加载的文件被列为单独的 JavaScript 文件。要获得有关的更多信息,请参阅 Foundation 网站 。

您必须进行的一个重要更改是,按由 Foundation 决定的加载顺序将所需的 JavaScript 文件组装成一个 JavaScript 文件。这意味着,要按正确的顺序将所有必要的 JavaScript 都复制和粘贴到一个文件中。如果所需的库使用了 jQuery,那么 jQuery 也要包含在该文件中。这个步骤绝对至关重要。如果它不正确,您可能会获得不一致的结果,或者 Coach 可能完全无法工作。在编译文件后,您可以在 Process Designer 中将该文件添加为 Web 文件,然后按需要将文件附加到 Coach 视图。在图 9 中,所有三个 JavaScript 文件都以正确的顺序被组装在 foundation.min.js 文件中。

图 9. 在 foundation.min.js 文件中的 JavaScript 文件

在 IBM Business Process Manager 中对 Coach 控件进行品牌化和定制

配置系统

与移动就绪文库的另一个重要的考虑因素是需要设置 viewport ,让页面能够相应地缩放。IBM BPM Coach 不会自动这样做,所以您必须对 Coach 视图中的 viewport 执行像下面的示例这样的设置:

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

在导入其他库时,可能会面临 CSS 类冲突的问题。在某些情况下,IBM BPM 会向组件添加额外的类,或者在不同的库中有相同名称的组件。要消除这些明显问题,最简单的方法是删除常备的样式表。可以使用下面的代码:

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");

此外,您可能还需要删除对常备 CSS 文件的所有引用。删除引用 CSS 文件的文档元素。主要的罪魁祸首是 coach_ng.css 文件。

构建第三方组件

导入正确的文件并配置系统后,可以采用与先前介绍的 Dojo 组件同样的方式构建组件,这意味着正确地使用 Coach 视图。如果 jQuery 是所包含文件集的一部分,您可以从 Coach 视图内的事件处理程序中调用 jQuery 函数。

回页首

利用 REST 协议扩展 IBM BPM Coach

另一个重要的考虑因素是包括 REST 协议。REST 已经成为 IBM BPM 的标准特性,利用 REST 可以支持更广泛的常备函数,在 UI 控件中也可以更容易使用这些函数。关于 Dojo REST 的最新使用信息,请参阅 dojo/request/xhr Dojo Toolkit 文档 。

用计时器实现此方法,开发人员可以快速创建可能需要频繁刷新的函数和显示,例如,任务列表。使用 REST,您可以轻松扩展 Foundation 画布外的菜单,用作移动就绪的 Process Portal,这只需增加一个定时器函数。

使用 Dojo XHR Request ,您可以轻松地收集信息,并在页面上使用它们。下面的代码示例包含的代码可用于检索特定任务的任务流,然后将其注入页面。不过,如前所述,您可能会想要声明一个 AMD 依赖关系,而不是使用 dojo.require 脚本。通过一个 Coach 视图的事件处理程序,或一个包含脚本中定义的函数,都可以很容易地执行 REST 请求。

代码示例

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   }); });}

回页首

结束语

本教程探讨了在 IBM BPM 中创建自定义 Coach 控件的不同方式,介绍 IBM BPM 中包含的 Dojo 框架,以及如何在没有提供其他包的情况下开发组件。本教程还研究了如何使用第三方框架(如 Foundation)来创建新的移动就绪的组件。最后,本教程演示了如何利用 REST 来提供所需的功能和移动就绪性。

致谢

作者希望感谢 James Carr 对本教程的审校和贡献。

正文到此结束
Loading...