Skip to main content

Introducing Formengine - The New Formbuilder, try for FREE formengine.io.

Designer UI Customization

availability

These features are available from version 5.0 onwards, with some limitations from version 4.0.

The architecture of the designer is highly flexible, allowing for extensive modification of the user interface, including toolbars, forms, modal windows, elements displayed on the canvas, validation, process updating, activity saving, etc. In this section of the documentation, you'll get acquainted with the tools and features of customization.

Designer Architecture

The designer consists of three main components:

  • WorkflowDesigner - a JavaScript object responsible for displaying the canvas, creating and managing elements on the canvas, including HTML and SVG templates, as well as interacting with the WorkflowEngine API.
  • HTML Templates - written using Vue.js, containing a Vue application initialization method and used for displaying and handling user interface elements on the canvas: toolbars, modal windows, and forms - all these are templates.
  • SVG Templates - used for displaying the workflow graph on the canvas: activities, transitions, comments, decisions, etc.
Angular & React

When using the WorkflowDesigner package for React or Angular, WorkflowDesigner is encapsulated within a component that controls the lifecycle of this object. HTML and SVG templates are still used to display elements inside the designer.

So, to summarize, the process of displaying the designer looks like this: in your client application, you instantiate WorkflowDesigner directly or use a ready-made React or Angular component. Through the WorkflowEngine API, WorkflowDesigner loads the workflow schema, data, plugins, activities, rules, etc.

Next, for each user interface element, a Vue application is created and initialized by calling the {template}_Init function loaded from HTML template, followed by calling the onUpdate method with the contextual data for this element.

A logical graph is also formed for the schema, and for each graph element, the SVG template rendering function is called, which interpolates the file using the data of that element. As a result, you see the schema and UI elements on the canvas.

Customizing HTML Templates

All HTML templates of the designer are located in the templates folder. This includes toolbars, modal windows, forms, pop-ups, and more. The templates consist of a {template-name}_Init function, which initializes the Vue application, its data, and methods; as well as HTML code based on the Element UI library for rendering the DOM of the user interface.

When a user opens the designer, the WorkflowDesigner object creates a Vue application for each interface element and loads content from the HTML template, for example, toolbar.html, then executes the initialization method, in the case of toolbar.html, the method name will be toolbar_Init. After that, the me.VueConfig.methods.onUpdate method will be called with specific data for this element.

You can customize any designer templates as you see fit, their appearance, and operation logic. For example, you can add additional validation when saving activities, remove some toolbar functions, or add new activity forms when using custom activities. Changes take effect instantly as templates do not require compilation, but templates are cached in WorkflowDesigner, so remember to clear the browser cache, for example in Chrome, press F12, right-click on the reload button, and select Empty cache and hard reload.

info

You can use designer property cacheLoadedFiles to disable template caching.

toolbar.html
<!-- rest code... -->

<el-tooltip :content="labels.Save" v-if="settings.showSaveButton">
<el-button :class="getButtonClass()" @click="save()">
<div class="WorkflowDesignerToolbarIcon Save RTLIcon"></div>
</el-button>
</el-tooltip>

<!-- rest code... -->

<script type="application/javascript">
function toolbar_Init(me) {
const data = me.VueConfig.data;

// You can get graph object
const graph = me.graph;

// You can get graph settings
data.settings = me.graph.Settings;

// You can get WorkflowDesigner object
const designer = me.graph.designer;

// You can get Vue object (version 8.0.0 and later)
const Vue = me.Vue;

// You can get Vue application instance (version 8.0.0 and later)
me.VueConfig.methods.onVueAppCreated = function (vueApp) {
console.log(vueApp)
}

// rest code...
me.VueConfig.methods.onUpdate = function (data) {
// rest code...
}

me.VueConfig.methods.save = function () {
// rest code...
};
}
</script>

Customizing SVG Templates

SVG templates are stored in the templates/elements folder and are used to display graph elements on the designer canvas. Each SVG template is a file with the extension .svg, containing a vector image of the element, styles, text, etc. During rendering, Workflow creates an SVG element on the canvas for each graph element.

You can also customize SVG templates as you see fit and even add new types of elements when using custom activities. In this case, you can use interpolation with {/* Some code */} to write executable JavaScript code to calculate properties based on the passed data of the graph element.

activity.svg

<svg direction="{BiDi}" width="{item.svgWidth = item.TextWidth + 20}" height="60" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="2" y="2" width="{item.TextWidth + 16}" height="56" rx="10" ry="10" fill="{Color}"
stroke="{item.Selected ? '#F39C12' : (item.IsInline? '#CECECE' : item.Color)}" stroke-width="3" stroke-linejoin="round"
stroke-dasharray="{item.IsInline? '8 4': 'none'}"/>
<text x="{item.mirrorX(9) }" y="19" font-family="Arial" font-size="12" font-weight="600" fill="{TextColor}">{Name}</text>
<text x="{item.mirrorX(9) }" y="32" font-family="Arial" font-size="12" fill="{TextColor}">{State}</text>
<text x="{item.mirrorX(9) }" y="49" visibility="{item.IsInitial ? 'visible' : 'hidden'}" font-family="Arial" font-size="12"
fill="{TextColor}">
{IsInitialLabel}
</text>
<!-- rest code -->
</svg>

Templates list

Form customization for Workflow Engine v4.2 and previous versions

remember

This section provides information for older and unsupported versions of the Workflow Engine.

When creating designer javascript object you can fill in the forms property in the object which will be transferred into the WorkflowDesigner constructor as configuration settings. This is how it looks in code:

var wfdesigner = new WorkflowDesigner({
// ...
forms: {
activity: function (params) {
},
transition: function (params) {
},
actors: function (params) {
},
commands: function (params) {
},
timers: function (params) {
},
codeactions: function (params) {
},
parameters: function (params) {
},
localization: function (params) {
},
legend: function (params) {
},
processinfo: function (params) {
}
},
// ...
});

As you can see in this code, to customize any window you need to write the following customization function:

function (params) {
// ...
}

and assign it to the appropriate edit window (for example, activity).

var wfdesigner = new WorkflowDesigner({
// ...
forms: {
activity: function (params) {
// do something
},
},
// ...
});

Customization function accepts the params object with the following properties:

  • params.data - data displayed in the form, this property is the object.
  • params.elements - description of the input fields which will be displayed in the form, this property is the objects array:
    [
    { name: "Name", field: "Name", type: "input" },
    { name: "State", field: "State", type: "input" }
    ]
    • name - name displayed in the form.
    • field - name of the params.data property, used for binding data to the form.
    • type - control type which will be displayed in the form (for example, "input", "textarea", "checkbox", etc.).
  • params.readonly - if returns true, the form is non-editable.
  • params.saveFunc - basic function to save forms.
  • params.title - form headline.

This is the basic algorithm of form customization using Customization function:

  • change the params object property.
  • create a new form object transferring the params into object constructor:
    var form = new WorkflowDesignerForm(params); 
  • create a save form function; it's a typical function, but you can write custom logic in it
    var saveFunc = function (data) {
    form.ClearTempField(data);
    // write any custom code here
    form.parameters.saveFunc(Object.assign(params.data, data));
    return true;
    };
  • call showModal function to show modal window.
    form.showModal(saveFunc);
    The result code will look like this:
    var wfdesigner = new WorkflowDesigner({
    // ...
    forms: {
    activity: function (params) {
    // change params object
    var form = new WorkflowDesignerForm(params);
    var saveFunc = function (data) {
    form.ClearTempField(data);
    // write any custom code here
    form.parameters.saveFunc(Object.assign(params.data, data));
    return true;
    };
    form.showModal(saveFunc);
    },
    },
    // ...
    });
note

A customization example for these versions can be read here.

Activity customization and transition rendering on the Designer canvas

When creating designer javascript object you can fill in the drawElements property in the object which will be transferred into the WorkflowDesigner constructor as configuration settings. This is how it looks in code:

var wfdesigner = new WorkflowDesigner({
// ...
drawElements: {
activity: function (element) {
},
transitionActivePoint: function (element, x, y) {
},
},
// ...
});
  • Customization function activity is responsible for rendering the activity box. The element object in the input is the WorkflowDesignerActivityControl object instance. Use element.item to access the object scheme description. The scheme element itself must be rendered into the element.control property. If this function returns false, a standard element will be rendered.
  • Customization function transitionActivePoint is responsible for rendering the transition central point. The element object in the input is the WorkflowDesignerTransitionControl object instance. Use element.item to access the object scheme description. The function should return the Konva.Group object as a result, which will be displayed on the canvas. If this function returns false, a standard element will be rendered.

More information related to rendering customization can be read in Konva.js documentation and the following example is also available.