[bpmn-js] How to bind to direct editing an element?

I have registered a command with the commandstack that changes the name of an element along with some other logic. I execute this command on user input. I want this command to be executed when the user direct-edits the element as well. How would I make it execute the custom command with the labeled element and the new label as context?

By digging around, I stumbled upon the provider api, but I can’t find any documentation on it. If this would solve my issue, how do I use it?

So you want to execute additional behavior whenever an element’s name is changed?

Yes, but a commandInterceptor wouldn’t work for updateProperties, because I have made commands set up to change the name along with this additional logic. If I use a command interceptor too, I would be executing this logic twice whenever I execute this command. I need to isolate the act of editing the name directly by double clicking.

Can you share your setup in a CodeSandbox? I’m not sure I understand it.

This will have intended behavior when changing the name through the input field in the top-right, but not when changing the name by double-clicking.

So you want custom behavior when the name of an element is changed? The right way of implementing this is a command interceptor instead of a new command handler. Thus, the original command will still be executed but the custom behavior will be executed as well.

This is how you’d add a command interceptor: https://codesandbox.io/s/bpmn-js-commandinterceptor-forked-mxzd0?file=/src/index.js

Alright, thanks! This works, though it’s kind of janky in my case. The issue is the additional logic I want to execute is another update-properties. That means this postExecuted would be executed twice, but I can simply check for what property was changed. Anyway thanks for the help!

Edit: it appears that wasn’t the reason postExecuted would be executed twice. It’s executed twice because any change to the name calls both element.updateLabel & element.updateProperties regardless. Is this intended behavior?

Executing updateProperties when updateProperties was executed will result in an infinite loop. You don’t want that. If you want to change the properties that will be updated you can hook in before the command is executed using preExecute and change the properties.

As in like so?

this.preExecute("element.updateProperties", function(ctx) {
    ctx.properties.id = "new-id";
}

Yes, that’s how you could do it. But be careful with IDs. You don’t want to have duplicate IDs.

1 Like

Alright thanks! I happened to discover an issue with your solution though. executing the function modeling.updateProperties will execute an element.updateLabel command as well. That means that the following CommandInterceptor will be executed twice.

this.preExecute(['element.updateLabel', 'element.updateProperties'], function ({ context }) {
    var { element, properties, newLabel } = context;
    if (properties && properties.name) {
        newLabel = properties.name;
    }
    if (newLabel) {
        assign(properties, { id: newLabel });
    }
});

I can’t think of any clean way of avoiding double execution. Do you have any suggestions?