How to initialize the BpmnModeler and the ElementRegistry after injecting bpmnjs?

Hi there,

I am looking to extend the modeler for personal fun, but actually do not know how to inject the BpmnModeler and the associated ElementRegistry from the bpmnjs injection. Please see the following code snippet:

var CamundaPropertiesProvider = require('bpmn-js-properties-panel/lib/provider/camunda/CamundaPropertiesProvider');

function GeneratedFormPreviewPluginProvider(injector, bpmnjs) {
  var camunda = new CamundaPropertiesProvider(...CamundaPropertiesProvider.$inject.map(dependency => injector.get(dependency)));

  console.log(bpmnjs);
}

GeneratedFormPreviewPlugin.$inject = ['injector', 'bpmnjs'];

function GeneratedFormPreviewPlugin() {

};

module.exports = {
  __init__: ['generatedFormPreviewPlugin'],
  propertiesProvider: ['type', GeneratedFormPreviewPluginProvider],
  generatedFormPreviewPlugin: ['type', GeneratedFormPreviewPlugin]
};

In the Camunda Modeler environment, this gives me the following in the console:

Unbenannt

Particularly, I am interested in using the data that can be found below “injector/_instances/canvas”:

Inked#2_LI

In case I am not mistaken, inside the location “injector/_instances/canvas” I can find the ElementRegistry and the Container for the BpmnModeler. However, how can I access those with the help of my bpmnjs injection and assign them to a new BpmnModeler instance and, subsequently, to a new ElementRegistry instance?

What I already tried is to initialize the BpmnModeler in above’s code snippet preambel, like the following:

var BpmnModeler = require('bpmn-js/lib/Modeler').default;

const bpmnModeler = new BpmnModeler({
  container: document.querySelector('#canvas'),
});
const moddle = bpmnModeler.get('moddle'),
      modeling = bpmnModeler.get('modeling');

var CamundaPropertiesProvider = require('bpmn-js-properties-panel/lib/provider/camunda/CamundaPropertiesProvider');

function GeneratedFormPreviewPluginProvider(injector, bpmnjs) {
  var camunda = new CamundaPropertiesProvider(...CamundaPropertiesProvider.$inject.map(dependency => injector.get(dependency)));

  console.log(bpmnjs);
}

GeneratedFormPreviewPlugin.$inject = ['injector', 'bpmnjs'];

function GeneratedFormPreviewPlugin() {

};

module.exports = {
  __init__: ['generatedFormPreviewPlugin'],
  propertiesProvider: ['type', GeneratedFormPreviewPluginProvider],
  generatedFormPreviewPlugin: ['type', GeneratedFormPreviewPlugin]
};

However, in this case, the BpmnModeler and the ElementRegistry remain empty.
Probably this is a really nooby question, but I spent a couple of hours and looked into several examples, so far without success.

Any kind of help is greatly appreciated.
Thank you in advance!

Your question seems to be about older versions of bpmn-js-properties-panel. While we are always going to try to answer your questions to the best of our abilities, we encourage you to consider using the latest version of bpmn-js-properties-panel. It makes creating your own extensions a lot easier! To get started with extending the properties panel check out this example: bpmn-js-properties-panel Extension Example.

In case you’re giving it a try, we’d love to hear your feedback! :heart:

If you need to stick to the old version, I am wondering why you don’t go the supported way of injecting services. For example

function MyExtension(canvas, elementRegistry) {
  console.log(canvas);
  console.log(elementRegistry);
}

MyExtension.$inject = ['canvas', 'elementRegistry'];

Is there any reason why do you play around with internals (bpmnjs.injector._instances)?

Hey Niklas,

thanks for your response. Well, I am trying to update the topic of a service task manually via code. When injecting the service “modeling”, I am not able to use the function “updateProperties”. E.g.:

function MyExtension(elementRegistry, modeling) {
  var serviceTask = elementRegistry.get("some-id");
  modeling.updateProperties(serviceTask, {name: "new name", topic: "new topic"});
}

MyExtension.$inject = ['elementRegistry', 'modeling'];

However, what works to some extent is the following:

var serviceTask = elementRegistry.get("some-id");
serviceTask.businessObject.topic = "new topic";

However, the change unfortunately does not get recognized in the xml immediately, which is why I am trying to update the model itself via “updateProperties”. However, without success. Any idea what I am doing wrong here?

Many thanks!

Hey,

finally got one step further. Please see the following:

var UpdatePropertiesHandler = require('bpmn-js/lib/features/modeling/cmd/UpdatePropertiesHandler').default;

function MyExtension(injector, elementRegistry, eventBus) {
  var serviceTask = elementRegistry.get("some-id");
  var updateProps = new UpdatePropertiesHandler(...UpdatePropertiesHandler.$inject.map(dependency => injector.get(dependency)));


  serviceTask.businessObject.name = "new name";
    updateProps.execute({
      element: serviceTask,
      properties: {name: "new name"}
    });
    eventBus.fire("element.changed", {element: serviceTask});
}

MyExtension.$inject = ['injector', 'elementRegistry', 'eventBus'];

However, I still recognize these changes to be not immediately updated in the xml of the model. Any final hints why this could be the case?

However, I still recognize these changes to be not immediately updated in the xml of the model.

Please make sure you use commands for it. Without, your changes won’t be maintained properly, and also not immediately updated. This example might be useful.

When injecting the service “modeling”, I am not able to use the function “updateProperties”

Why though? Which error is thrown? Are you able to show this inside a CodeSandbox?

If you want to update nested properties (as extension elements), probably the Modeling.updateModdleProperties command would be better suiting.