bpmn-js Examples

repository·main·Indexed 24 days ago

https://github.com/bpmn-io/bpmn-js-examples

A collection of practical examples for integrating, extending, and customizing the bpmn-js library. Includes guides on reading and writing BPMN properties with and without undo/redo support, bundling with Webpack and Rollup, implementing custom renderers, adding colors via overlays or BPMN 2.0 extensions, and creating custom elements, palette controls, and context pads.

Tokens
29.1K
Snippets
101
Records
132
Agent score
85%

What's inside bpmn-js-examples

  1. Build the bpmn-js commenting discussion app

    main
    This example demonstrates how to build a simple discussion application using bpmn-js and the bpmn-js-embedded-comments extension. It embeds a BPMN diagram and allows users to add comments to individual tasks. These comments are stored within the element's <bpmn:documentation> tag and are included when the diagram is downloaded.
  2. Embed bpmn-js into HTML pages

    main

    This example demonstrates how to embed different versions of the bpmn-js toolkit into a larger HTML website.

    A key feature of recent versions is that diagram containers are focusable elements. This ensures that each instance of the modeler only captures keyboard shortcuts when it is actively focused, preventing interference with other native or custom elements on the page.

  3. Add colors to BPMN diagrams via Custom Renderer

    main

    For highly dynamic or complex coloring logic (such as coloring shapes based on task priorities), you can implement a custom renderer. This involves providing a class that overrides how specific BPMN elements are rendered.

    For a concrete implementation reference, see the bpmn-js-task-priorities repository.

  4. Replace the default renderer in bpmn-js

    main
    You can replace the default rendering engine by providing a custom renderer. Examples include using bpmn-js-sketchy for a hand-drawn look or implementing your own renderer logic (similar to how bpmn-js-nyan or custom element examples are implemented).
  5. Implement custom modeling rules in bpmn-js

    main

    You can extend the bpmn-js modeler by implementing a custom rules provider. This allows you to intercept and restrict modeling actions, such as element creation.

    To restrict element creation, you can hook into the shape.create rule. The rule evaluation function receives a context object containing the shape being created and its parent. By inspecting the businessObject of the target parent (using .get('attributeName')), you can decide whether to allow or deny the creation of specific shapes based on custom extension attributes.

    In this example, the rule checks for a vendor:allowDrop attribute on the target element. If the attribute is missing or the new shape does not match the type specified in the attribute, the rule returns false, preventing the creation.

    this.addRule('shape.create', function(context) {
    
      var shape = context.shape,
          target = context.parent;
    
      var shapeBo = shape.businessObject,
          targetBo = target.businessObject;
    
      var allowDrop = targetBo.get('vendor:allowDrop');
    
      if (!allowDrop || !shapeBo.$instanceOf(allowDrop)) {
        return false;
      }
    });
  6. Create a PropertiesProvider to organize UI groups

    main

    A PropertiesProvider defines how custom properties are organized into tabs, groups, and input elements. You register it using propertiesPanel.registerProvider(priority, provider).

    To ensure your custom properties appear alongside standard BPMN properties, use a lower priority. Use the getGroups method to inject your custom groups into the panel based on the selected element.

    function MagicPropertiesProvider(propertiesPanel, translate) {
      // Register with a lower priority to load after basic BPMN properties
      propertiesPanel.registerProvider(LOW_PRIORITY, this);
    
      this.getGroups = function(element) {
        return function(groups) {
          // Only show the 'magic' group if a Start Event is selected
          if(is(element, 'bpmn:StartEvent')) {
            groups.push(createMagicGroup(element, translate));
          }
          return groups;
        }
      };
    }
    function MagicPropertiesProvider(propertiesPanel, translate) {
    
      // Register our custom magic properties provider.
      // Use a lower priority to ensure it is loaded after the basic BPMN properties.
      propertiesPanel.registerProvider(LOW_PRIORITY, this);
    
      ... 
    
      this.getGroups = function(element) {
    
        ... 
    
        return function(groups) {
    
          // Add the "magic" group
          if(is(element, 'bpmn:StartEvent')) {
            groups.push(createMagicGroup(element, translate));
          }
    
          return groups;
        }
      };
    }
  7. Understand Custom Elements in bpmn-js

    main

    Custom elements in bpmn-js are standard BPMN 2.0 elements augmented with domain-specific data, appearance, and behavior. They allow you to:

    • Display elements in a distinct visual way.
    • Restrict modeling rules (where elements can be placed).
    • Attach metadata like KPI targets or performance analytics.
    • Display technical or hidden details directly on the diagram.

    Note on Data Lifecycle: If your data is transient (e.g., runtime data) or stored outside the BPMN 2.0 XML file, use overlays instead of custom elements.

  8. Implement deep-linking with Canvas#setRootElement

    main

    You can implement deep-linking (switching between different diagram layers/subprocesses) by using the Canvas service from bpmn-js.

    To switch the view to a specific element, use the setRootElement method. When targeting collapsed subprocesses, you must append the _plane suffix to the element's ID to correctly access the diagram layer.

    1. Access the canvas service using bpmnViewer.get('canvas').
    2. Call canvas.setRootElement(id) with the target element ID (or id + '_plane' for collapsed subprocesses).
    var canvas = bpmnViewer.get('canvas');
    
    // switch to a collapsed subprocess
    canvas.setRootElement('collapsedProcess_plane');
  9. How to access and read BPMN properties

    main

    In bpmn-js, every diagram element contains a businessObject property. This businessObject is the actual underlying BPMN element that corresponds to the BPMN 2.0 XML. To read BPMN-specific properties (like name or conditionExpression), you must first obtain the element from the elementRegistry and then access its businessObject.

    Note that the businessObject is what gets imported from XML and serialized during export.

    var elementRegistry = bpmnJS.get('elementRegistry');
    
    var sequenceFlowElement = elementRegistry.get('SequenceFlow_1'),
        sequenceFlow = sequenceFlowElement.businessObject;
    
    sequenceFlow.name; // 'YES'
    sequenceFlow.conditionExpression; // ModdleElement { $type: 'bpmn:FormalExpression', ... }
  10. Initialize interaction after loading a diagram

    main

    Interaction listeners should only be attached after the BPMN diagram has been successfully imported into the viewer or modeler. Use the importXML method and wait for it to resolve before attempting to access the eventBus or the DOM.

    var viewer = new BpmnJS({ container: SOME_CONTAINER });
    
    try {
    	await viewer.importXML(diagramXM);
    
    	// diagram is loaded, add interaction to it now
    	// see below for options
    	// ...
    } catch (err) {
    	console.error('Error happened: ', err);
    }