Hi there,
I’m styling the BPMN SVG using CSS and I need to add the type of the element in all corresponding svg elements. Something like that:
<g class="djs-element djs-shape" data-element-id="IntermediateThrowEvent_1w7puvt" data-element-type="bpmn:IntermediateCatchEvent">
...
</g>
I could archive it by doing
bpmnModeler.importXML(xml, function(err) {
var canvas = _this.bpmnModeler.get('canvas');
var elements = canvas._elementRegistry._elements;
for (elm in elements) {
// Set the attribute with the element type, to apply css
elements[elm].gfx.setAttribute("data-element-type", elements[elm].element.type);
}
});
The problem is that when creating new elements, changing, etc. the solutions is no longer valid. So I came up with another solution that works for me. I change the method ElementRegistry.prototype.add direct in the .js file to set the new attribute the same way the attribute data-element-id is set.
...
var ELEMENT_TYPE = 'data-element-type';
ElementRegistry.prototype.add = function(element, gfx, secondaryGfx) {
...
attr$1(gfx, ELEMENT_TYPE, element.type);
...
};
This works as expected, but I want to create a bundle for myself overriding the default behavior of ElementRegistry.prototype.add. I’ve already have my bundle generated using rollup using the umd format. I tried adding the following as module and did not work
import inherits from 'inherits';
import ElementRegistry from 'diagram-js/lib/core/ElementRegistry';
var ELEMENT_TYPE = 'data-element-type';
export default function AddElementType(eventBus) {
ElementRegistry.call(this, eventBus);
}
inherits(AddElementType, ElementRegistry);
AddElementType.$inject = ['eventBus'];
AddElementType.prototype.add = function (element, gfx, secondaryGfx) {
console.log(element);
};
How could I override this method? Is there a better approach?
Thank you!
What are you trying to achieve?
Apply real time color customization to the generated SVG, using svg filters. I have a open WebSocket connection that change some attributes of the svg in real time to apply different style for each element type.
In order to do so I need to differentiate all BPMN elements one of another by type. Each type will have your own custom CSS. Something like:
[data-element-type*="Task"][data-v-10] > g > rect { filter: url(#t10) !important; }
[data-element-type*="Task"][data-v-20] > g > rect { filter: url(#t20) !important; }
...
[data-element-type^="bpmn:Intermediate"][data-v-10] > g > circle:first-child { filter: url(#i10) !important; }
...
I know I can do it differently, but I think keeping it in CSS it will be easier to maintain by the design team and I also don’t want to redraw the svg every time a have I change returned by the WebSocket.
Thanks.
I manage to do it replacing the “elementRegistry” with my custom module implementation.
import CustomElementRegistry from './CustomElementRegistry';
export default {
__init__: [
'elementRegistry'
],
elementRegistry: ['type', CustomElementRegistry]
};
Module implementation is now:
import inherits from 'inherits';
import { attr as svgAttr } from 'tiny-svg';
import ElementRegistry from 'diagram-js/lib/core/ElementRegistry';
var ELEMENT_TYPE = 'data-element-type';
export default function CustomElementRegistry(eventBus) {
ElementRegistry.call(this, eventBus);
}
inherits(CustomElementRegistry, ElementRegistry);
CustomElementRegistry.$inject = ['eventBus'];
CustomElementRegistry.prototype.add = function (element, gfx, secondaryGfx) {
CustomElementRegistry.super_.prototype.add.call(this, element, gfx, secondaryGfx);
// associate dom node with element
svgAttr(gfx, ELEMENT_TYPE, element.type);
if (secondaryGfx) {
svgAttr(secondaryGfx, ELEMENT_TYPE, element.type);
}
};
Thank you.
Have you discovered Modeling#setColor
yet?
At first, when I was trying to archive what I want, I was testing all options shown on the project colors on bpmn-js-examples. I couldn’t make the option 2 Modeling#setColor
work on both the Modeler and the Viewer, it worked only on the Modeler. I also tried to import modeling to my Viewer bundle but it didn’t worked, showing lots of errors (I don’t know if I did something wrong).
As I wanted the same solution for both the Viewer and the Modeler I decided to go with something like the option 3, that is working with CSS the way I showed here.
I appreciate the time you spent trying to help! Thank you!
The point of the viewer is that it’s not a modeler, therefore you cannot change the imported diagram in the viewer hence you can’t change an element’s color.
One solution to this is using the low-level APIs that are being used when changing an element’s color. Here’s an example: https://github.com/bpmn-io/bpmn-js-token-simulation/blob/master/lib/features/preserve-element-colors/PreserveElementColors.js#L52