preface

ο£Ώ

Q: What is bPMn.js? πŸ€” ️

Bpmn. js is a BPMN2.0 rendering toolkit and Web modeler that allows you to draw flowcharts in the front end.

ο£Ώ

Q: Why did I write this series? πŸ€” ️

Due to the business needs of the company, bPMN. js is used in the project. However, as the developer of BPMN. js is a foreign friend, there are few textbooks and no detailed documents on this aspect in China. So a lot of ways to use a lot of pits have to find their own. After mulling it over, I decided to write a series of textbooks on it to help more bPMn.js users or developers who want to find a good way to draw flowcharts. It is also a kind of consolidation of their own.

Because it is a series of articles, so the update may be more frequent, if you accidentally brush and not what you need also please understand 😊.

Don’t ask for praise πŸ‘ don’t ask for heart ❀️. I only hope to have a little help for you.

Customize the Palette article

After the basic tutorial of the previous chapters, we believe that you have a good grasp of the basic use of BPMn.js.

Starting with this chapter, I will cover some of the customization aspects of bPMn.js, including custom left toolbar, custom render, custom contextPad, and more.

Let’s take a look at an image to see what’s on our drawing page:


In this chapter, I will describe how to customize the left side of the toolbar, which is also called the Palette. You can read the following information:

  • Change it from the default Palette
  • Fully customize the Palette

For πŸ‘†, you can customize the Palette in two ways:

  • inbpmn.jsProvided by defaultPaletteTo modify (or add a new item)
  • Complete coveragePaletteFor all items in, customize a brand new onePalette

Change it from the default Palette

Let’s take a look at the first and simplest option, which is to add a custom item to the official palette.

  • Element type:bpmn:Task
  • Element name:lindaidai-task
  • Style: Followbpmn:TaskThe original style, but the border is red
  • Creates a file of typelindaidai-taskTask node of

It works like this:

bpmnCustom1.png

As shown above, I only changed the color of the taskbox to red, so the effect is not obvious, and you can even change the look of the taskbox directly:

bpmnCustom2.png

Let’s see how to implement it. 🐢

preparation

Since it is a new chapter, I will also create a new project here:

$ vue create bpmn-vue-custom
$ npm i vue-router axios bpmn-js-properties-panel bpmn-js --save-D
Copy the code

Follow the previous example LinDaiDai/ BPMN-VUE-basic to configure the corresponding routing and so on.

In the Components folder, create a new file named Custom-palette. Vue and copy the contents of provider.vue(the previous base case) into it.

Go ahead and create a new folder under Components called Custom to hold some of the customization we’ll write later.

Take a look at our current project structure:


I have created a new CustomPalette. Js in the Custom folder, and the next step is to write the item we want to customize in this folder.

writeCustomPalette.jscode

First, this js is exporting a class (you can call it whatever you like, but you can’t call it when referencing it, as we’ll see later):

So I’ll just call it “CustomPalette” :

// CustomPalette.js
export default class CustomPalette {
    constructor(bpmnFactory, create, elementFactory, palette, translate) {
        this.bpmnFactory = bpmnFactory;
        this.create = create;
        this.elementFactory = elementFactory;
        this.translate = translate;

        palette.registerProvider(this);
    }
    // This function is the core of the palette
    getPaletteEntries(element) {}
}

CustomPalette.$inject = [
    'bpmnFactory'.'create'.'elementFactory'.'palette'.'translate'
]
Copy the code

The code for πŸ‘† above is easy to understand:

  • Define a class
  • use$injectInject some needed variables
  • Used in a classpalette.registerProvider(this)Specify that this is apalette

After defining CustomPalette. Js, we need to export it in its sibling index.js:

// custom/index.js
import CustomPalette from './CustomPalette'

export default {
    __init__: ['customPalette'].customPalette: ['type', CustomPalette]
}
Copy the code

Note: the name in ️ __init__ must be the customPalette, and the property name below must also be the customPalette, otherwise it will be an error.

Also use it in the page:

<! --custom-palette.vue-->
<script>. import customModulefrom './custom'. this.bpmnModeler =new BpmnModeler({
...
    additionalModules: [
        // Left toolbar and node
        propertiesProviderModule,
        // A custom node
        customModule
    ]
})

</script>
Copy the code

Write core functionsgetPaletteEntriescode

All that aside, how do you construct the getPaletteEntries function

You can’t change the name of the function or you’ll get an error. First, it returns an object that specifies the item you want to customize. It looks something like this:

// CustomPalette.js
getPaletteEntries(element) {
    return {
        'create.lindaidai-task': {
            group: 'model'./ / group name
            className: 'bpmn-icon-task red'.// Style class name
            title: translate('Create a task node of type Lindaidai-Task'),
            action: { / / operation
                dragstart: createTask(), // The event called when the drag begins
                click: createTask() // The event that is invoked when clicked}}}}Copy the code

You can see that the name of one of the items I defined is: create.lindaidai-task. It will have several fixed properties:

  • Group: Belongs to a group, for exampleTools, Event, Gateway, activityAnd so on, for classification
  • ClassName: The name of the style class that we can use to style elements
  • Title: The prompt given by moving the mouse over the element
  • Action: Events triggered when users perform operations

What we are going to do is:

  1. throughclassNameTo set the style
  2. throughactionTo define what to trigger

writeclassNamecode

I created a new CSS file in the SCR directory to hold some global styles and referenced them in main.js:

// main.js
// Introduce global CSS
import './css/app.css'
Copy the code

Then add a style to it:

/* app.css */
.bpmn-icon-task.red {
    color: #cc0000 ! important;
}
Copy the code

The className πŸ‘† above the reason why I want to use BPMN – icon – a task, because this class is BPMN. Own a iconfont class in js, use it can achieve the effect of a task icon:


Since iconfont is a font, I use color to change its color.

You can also use className if you want to change the image completely:

/* app.css */
.icon-custom { /* Define a common class name */
    border-radius: 50%;
    background-size: 65%;
    background-repeat: no-repeat;
    background-position: center;
}

.icon-custom.lindaidai-task { /* add background */
    background-image: url('https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/rules.png');
}
Copy the code

Then modify the className in create.lindaidai-task:

// CustomPalette.js
 'create.lindaidai-task': {
    className: 'icon-custom lindaidai-task' 
 }
Copy the code

Now the page displays the background image you defined:

bpmnCustom4.png

writeactioncode

With this done, the page renders a custom element normally, but it doesn’t work when you click or drag it πŸ’¦.

What we want is to click or drag it to draw a Lindaidai-task on the canvas, so you need to add an event to it, which is to write a function that creates the BPMN :Task element:

// CustomPalette.js function createTask() { return function(event) { const businessObject = bpmnFactory.create('bpmn:Task'); const shape = elementFactory.createShape({ type: 'bpmn:Task', businessObject }); Console. log(shape) creates. Start (event, shape) only when dragging or clicking; }}Copy the code

The core here is to create shapes using the methods provided by BPMn.js and then add them to the canvas.

(You can also create BPMN :StartEvent, BPMN :ServiceTask, BPMN :ExclusiveGateway, etc.)

Drag or click Lindaidai-Task to create a Task element on the page.


We can see that lindaidai-Task is golden yellow on the left toolbar, but it is still “naked” on the page πŸ˜…. This has to do with custom rendering, which will be covered in a later chapter.

The completeCustomPalette.jscode

Let’s put all the above code together:

// CustomPalette.js
export default class CustomPalette {
    constructor(bpmnFactory, create, elementFactory, palette, translate) {
        this.bpmnFactory = bpmnFactory;
        this.create = create;
        this.elementFactory = elementFactory;
        this.translate = translate;

        palette.registerProvider(this);
    }

    getPaletteEntries(element) {
        const {
            bpmnFactory,
            create,
            elementFactory,
            translate
        } = this;

        function createTask() {
            return function(event) {
                const businessObject = bpmnFactory.create('bpmn:Task'); // This is not necessary
                const shape = elementFactory.createShape({
                    type: 'bpmn:Task',
                    businessObject
                });
                console.log(shape) // Trigger only when you drag or clickcreate.start(event, shape); }}return {
            'create.lindaidai-task': {
                group: 'model'.className: 'icon-custom lindaidai-task'.title: translate('Create a task node of type Lindaidai-Task'),
                action: {
                    dragstart: createTask(),
                    click: createTask()
                }
            }
        }
    }
}

CustomPalette.$inject = [
    'bpmnFactory'.'create'.'elementFactory'.'palette'.'translate'
]
Copy the code

Git address: LinDaiDai/ bPMn-vue-custom

Note: in the project case, I used thecustom-paletteIs introduced inImportJS/onlyPalette.js, and the above case is introducedcustom/index.jsFor the sake of explanation, you have to figure out how to distinguish this.

Fully customize the Palette

As you can see, the implementation of πŸ‘† above essentially defines a CustomPalette and references it in the object generated by New BpmnModeler.

The downside of this πŸ‘Ž is that if you don’t want the default start node, end node, and task node, you won’t be satisfied. Like this:

bpmnCustom6.png

At this point, you need to rewrite the BpmnModeler class to implement your own set of Modelers.

preparation

Go ahead and create a customModeler folder and a custom-Modeler.vue file based on the project at πŸ‘† above. Then create an index.js and a Custom folder in customModeler.

  • customModelerThe files under the folder are used to store customizationsmodeler
  • custom-modeler.vuePresent as a page (remember to configure routing for the page)

The project structure now becomes:

bpmnCustom7.png

writeCustomPalette.jscode

The CustomPalette. Js is written differently from the first one:

/** * A palette that allows you to create BPMN _and_ custom elements. */
export default function PaletteProvider(palette, create, elementFactory, globalConnect) {
    this.create = create
    this.elementFactory = elementFactory
    this.globalConnect = globalConnect

    palette.registerProvider(this)
}

PaletteProvider.$inject = [
    'palette'.'create'.'elementFactory'.'globalConnect'
]

PaletteProvider.prototype.getPaletteEntries = function(element) { // This method is the same as the above example
    const {
        create,
        elementFactory
    } = this;
    function createTask() {
        return function(event) {
            const shape = elementFactory.createShape({
                type: 'bpmn:Task'
            });
            console.log(shape) // Trigger only when you drag or clickcreate.start(event, shape); }}return {
        'create.lindaidai-task': {
            group: 'model'.className: 'icon-custom lindaidai-task'.title: 'Create a task node of type Lindaidai-Task'.action: {
                dragstart: createTask(),
                click: createTask()
            }
        }
    }
}
Copy the code

Here we have overwritten the PaletteProvider class and overwritten the getPaletteEntries method on its prototype to override the original toolbar.

(don’t look at the above πŸ‘† write things seem to be a lot of appearance, but actually calm down to find nothing 😊)

writecustom/index.jscode

Next, we need to export our custom Palette as in the first method:

// custom/index.js
import CustomPalette from './CustomPalette'
export default {
    __init__: ['paletteProvider'].paletteProvider: ['type', CustomPalette]
}
Copy the code

But instead of going to the customPalette, we’re going to go straight to the paletteProvider.

writecustomModeler/index.jscode

The most important step is to write the CustomModeler class:

import Modeler from 'bpmn-js/lib/Modeler'
import inherits from 'inherits'
import CustomModule from './custom'
export default function CustomModeler(options) {
    Modeler.call(this, options)
    this._customElements = []
}
inherits(CustomModeler, Modeler)
CustomModeler.prototype._modules = [].concat(
    CustomModeler.prototype._modules, [
        CustomModule
    ]
)
Copy the code

The exported class inherits the core Modeler class, thus ensuring the implementation of other functions.

Reference on the page

The last step is to change the object we originally created through BpmnModeler to our custom Modeler and write custom-modeler.vue.

<! --custom-modeler.vue-->
<script>. import CustomModelerfrom './customModeler'. this.bpmnModeler =new CustomModeler({ // This is BpmnModeler. additionalModules: []// You don't need to reference anything
})
</script>
Copy the code

Let’s open the page and see what it looks like:

bpmnCustom8.png

After the language

The above two cases πŸ‘† use the same project 🦐

Project case Git address: LinDaiDai/ bPMn-vue-custom Please give a Star🌟, thanks 😊

For the full catalogue of the series, please check here: “The most detailed BPMN.js textbook in the whole Web”.

Series related recommendations:

“The most detailed BPMN.JS textbook in the Whole Web – Basic Chapter”

The most detailed BPMN.js textbook in the whole web – HTTP Request

The most detailed BPMN.JS textbook in the whole Web – Events

The most detailed BPMN.js textbook on the Whole web – Renderer

The most detailed BPMN.js textbook -contextPad

“The most detailed BPMN. js textbook in the whole web – Editing and Deleting nodes”