Adventures in Custom Elements... making the html A tag


First word and note… I am a complete new person to this software. I have done my best to not only understand the format but as much of the underlying code as I can. It is still impressively complex. Still I am possibly asking a stupid or maybe non-sensible question, but I am wanting to see what I can learn.

My department wants me to make an new bpmn object that essentially works like a html A tag. You can click on it to open a noted other diagram in a separate tab. My plan was to make a custom object, and have it contain an ID code that I would store in my data base, and when that ID is called from y data base the XML data would load in and open up as a existing bpmn diagram in a separate tab.

So I would need to make or over write an existing object, and have it somehow store the data of the document. Then I can make a custom event when it is clicked on to open the desired data in a new tab.

So. I looked at the examples for a reference. The one named “Custom Elements” seems to sorta make new elements, but they don’t store int he XML. Instead it seems to use data which is off in a json file. I don’t know why they would do that, but that seems to be what is done. I need the data to be stored in the bpmn xml file generated at save.

I also looked at the Nyan cats example which seems to sorta make a custom element. If I am understanding correctly it looks like it is more hijacking an existing element and re-defining it. Sorta. It is shorter and simpler, and I had an easier time understanding it, but I am not sure what I want to do is to hijack an existing element in order to do what I want to do. Not to mention the fact that I still don’t know how I can store the extra data that I want to. My implementation of BPMN uses the commenting system so I can;t store the data as a comment without it looking weird when people open comments.

Any suggestions would be welcome.

As to providing a link showing an example of what I am doing, I can’t as it is behind my companies firewall. Still for the most part is standard BPMN with commenting added much like the example provided, and the properties panel much like shown in its example.

The only thing I have added that is extra is a ajax code that calls to an API and provides the ability to load and save data to a MS sql database.


Hi @jeremy.mone

although your code is behind your companies firewall, I really want to encourage to give us some example code so we can help you in detail. Since we do not know how your actual implementation of your custom / comment element looks like, it’s hard to help you.


Providing any kinds of mock-ups that illustrate your goal would help us tremendously, too.


What I have is mostly the same stuff as in the examples quite honestly. Not much is custom anything on its own.

Still I think part of what I want to know may be more about the BPMN XML standard than the code. What I want to create is a custom object that gets included with the XML written out when the saveXML feature is called. I would like to have it save to a bpmn xml that won’t freak out Cawemo or other BPMN editors if they load. So I am wondering if there is a type of custom elements in the xml that I can manpulate and fill with special data that other editors would just turn into something benign or just straight ignore but not crash. A number of my co-workers use Cawemo so it would be nice if I made it so at least Cawemo can read the bpmn.xml doc produced on save without freaking out.

So… The example I understand the best when it comes to custom objects is the nyan cat example. I have what I feel is a firm grasp of how it works code wise, but the output xml is like this:

<?xml version="1.0" encoding="UTF-8"?>
<bpmn2:definitions xmlns:xsi="" xmlns:bpmn2="" xmlns:bpmndi="" xmlns:dc="" xmlns:di="" id="2750ca85-1a00-a369-7c07-1fbe929dd217" targetNamespace="" xsi:schemaLocation=" BPMN20.xsd">
  <bpmn2:process id="Process_1" isExecutable="false">
	  ... stuff clipped ...
    <bpmn2:serviceTask id="ServiceTask_14wq29l">
      <bpmn2:documentation textFormat="text/x-comments">:Comment on Nyan</bpmn2:documentation>
	  ... stuff clipped ...
  <bpmndi:BPMNDiagram id="BPMNDiagram_1">
    <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
	  ... stuff clipped ...
      <bpmndi:BPMNShape id="ServiceTask_14wq29l_di" bpmnElement="ServiceTask_14wq29l">
        <dc:Bounds x="862" y="357" width="100" height="80" />
	  ... stuff clipped ...

I know what the nyan cat is doing… it is essentially hijacking the bpmn2:serviceTask object, and making it look different mostly. Not much else. I assume all the business rules it has are the same as the serviceTask and the whole nine yards. It just has a cute cat graphic running in place.

So it got me thinking and wanting to ask… Is there a bpmn2:ignorableObjectThatWontKillCawemo that I can override or extend. It would be great if I could give it bpmn2:documentation sub elements that I can use to store data in as well.

I want anything I create and edit to store and save into the XML, and I would highly prefer if this XML could be loaded into Cawemo, but simply ignored or looks like something else like the data document or some such.

I have been searching for a list of all the possible acceptable XML elements that is part of the standard with the hope they may a couple of handful of bpmn2:customElement1(2, 3, 4, etc) that I can use to make special stuff I can save in the xml and not break other things.

So I think I am repeating myself, and I will leave it there.

This is my first time reaching out to a for help in a written form so I am a bit unused to it. I do apologize, and I appreciate your time and help int his matter. I am hoping to spark some ideas or find more resources that may help guide me a bit better down this rabbit hole I am travelling.

Thank you for your time and patience!

x Jeremy Mone



So you click on the Plus sign, or maybe just on the element itself, and it fires off some javascript code that opens a “linked” diagram in a different tab.

That is the main idea. So it gives me a way to create objects that can be used to represent other diagrams which can be opened on their own. You can do that in the diagram opened up as well and link to yet more diagrams. Keep going this way inception style as much as you like. You want to get back to where you were? Close the browser tab it was opened up in, or shift back the the tab you came from.

So you can make a process diagram that can lead to other process diagrams. I would probably make an api that would open the diagram with my modeler with some code that references a saved bpmn xml in my microsoft sql database (already have that part done actually).

Does that make sense as to what the mock-up design is intended to be?

Hoping I am making this more clear instead of less. Thank you immensely for your time and help!

x Jeremy M.


If I understand you correctly, you request two features:

(1) Opening multiple diagrams in different tabs: This essentially means you got multiple modeler instances, that show different diagrams. Just build it and it would work (cf. Camunda Modeler, an application that implements this).

(2) Opening linked diagrams: Following the interaction example you may be able to register to ‘click’ events on an element. Simply intercept that click, figure out which diagram is linked (this is the tricky part) and proceed to step (1).

As far as I am aware non of your requirements requires an actual HTML<a/> tag to be rendered / injected.


Yes. I think you got it right. I didn’t want a literal A tag to be rendered. I wanted to make something that worked much like an A tag. Gives me the same ability to click on an element, and it will open a different document or different full instance of the modeler in a different browser tab or browser window. I would click on it and it would work much like (but not exactly as):

<a href="" target="_blank"></a>

Again I don’t need it to create a literal A tag to be clicked on. I just need to make it so when the element is clicked on it will have the data somehow stored on the XML that has “3bsdj354”, and it will know to fire off the javascript code:

let url = "" + database_id;, "_blank");

I am pretty sure I can accomplish this with the existing features and code already in BPMN. The hard part as you said is making it so the database_id is saved in and loaded from the bpmn xml. Then I need to either create a new custom object that can do the actions, or I need to be able to add that data to an existing object and make it so if that existing object has said extra data then it responds a bit different when clicked. Something like that.

Also trying very hard to make the saved bpmn xml be something that can be loaded without issue into other bpmn xml based modelers like Cawemo and the like. Why I would like to try to give maybe an existing element a bit of double duty if I can somehow add additional data to it in a way that the base modeler will validate properly.


We’re exporting valid XML and Cawemo uses our toolkit under the hood :drum:. Everyting you can feed into bpmn-js as a library you’ll also be able to feed into Cawemo.


Very true. Just afraid that if I make a custom object/element that it will stop working on cawemo so I want to do something that will mesh well without losing the data even if it may not quite work right on cawemo. If that makes sense at all.


I have been looking at these items:

which also references:

and I am wondering if this is closer to the mark I seem to be wanting to hit? Am I barking up the right tree you think?


Regardless of the way you implement your hyperlinks it’s not possible to implement them in way that a URL is opened whenever you click on an element. That’s not possible without customizing the modeler itself.


I have seen where you can detect when an element is clicked on you can do things. If I can detect that the element has additional data on it (I am assuming that event bus broadcast will have the element info attached to it), then I can check to see if a particular set of data is there, and then run a function tied to that event which runs some javascript. I grab the Database_ID from the data on the element, and run the javascript that does a“my url”+Database_ID, “_blank”); and presto a new window is opened with the script on that url know what to do with the code and opening a new modeler with a different bpmn.xml in it.

So of that I know how I am going to do it. When I actually get something put together that can do it, then I will be happy to share that code on here as well. What I don’t know is how I am going to get that data into the model in such a way that it will save and load in the bpmn.xml that is generated when calling a modeler.saveXML(). I also have the constraint that the way it saves the data should be something that preferably will not prevent it from being loaded “as is” into cawemo. Even if used in cawemo it shouldn’t lose that data either. Should go in and come back out of cawemo unaffected, and my modeler would know what to do with it when present.

So what I am mostly trying to figure out is how to get the data into the model in a compliant way, and have it save and load without issue. How I use the data will be a special thing I do by branching off a element click event and pulling desired data and doing something special.

A lot hinges on what I can and cannot put into the xml save in a way that it will be loaded later without issue.


You can use custom click handlers to open URLs on click. That approach will not help users of Cawemo, though, as you can’t customize the Cawemo modeler.


That is fine so long as the save file of bpmn xml still has the data that can be read by my site. It is ok that it is not used in cawemo.


Do you want these hyperlink elements to be seperate elements? You could also just have a custom attribute on an element and offer opening the specified link.


Not separate elements. Just custom attributes that I will set my modeler to react to when the element is clicked on. Yet something that properly saves into the XML, and doesn’t create a fuss in cawemo the the xml is passed into that app, and will pass out of cawemo to if exported as a bpmn xml file.

Basically overload an existing object (element?) with additional data, and I will have a click event that uses that data to open a new browser window or tab with the info in the tagged into the URL so the modeler/viewer knows with database data to load and use for the xml of that new tab or window.


That is easily possible. Have you had a look at this example?