Stuck in creating custom input parameter in xml

I want to generate dynamic input parameter in XML like below

      <bpmn:extensionElements>       
        <camunda:inputOutput>
          <camunda:inputParameter name="John">John is very smart</camunda:inputParameter>
        </camunda:inputOutput>
      </bpmn:extensionElements>

My json model,

{
    "name": "Input",
    "prefix": "input",
    "uri": "http://Input",
    "xml": {
      "tagAlias": "lowerCase"
    },
    "associations": [],
    "types": [
      {
        "name": "StartEvent",
        "extends": [
          "bpmn:Activity",
        ],
        "properties": [
          {
            "name": "output",
            "isAttr": true,
            "isMany": true,
            "type"  : "array"
          },
          {
            "name": "IsStartable",
            "default": true,
            "isAttr": true,
            "type"  : "Boolean"
          }
        ]
      },
      {
        "name": "inputOutput",
        "superClass": ["Element"],
        "properties": [
          {
            "name": "inputParameter",
            "isMany": false,
            "type": "String"
          }
        ]
      },
      {
        "name": "inputOutput",
        "properties": [
          {
            "name": "name",
            "type": "String",
            "isAttr": true
          },
          {
            "name": "text",
            "isBody": true,
            "type": "String"
          },
        ]
       }
    ]
  }

The problem with the above model I can’t use prefix as “camunda” instead of “input”, if I set camunda as a prefix then it throws me the error.

My code,

 var bpmnModel = window.bpnModel;
          var moddle = bpmnModel.get('moddle');
          var inputParameter = moddle.create('camunda:InputParameter', {
            name: 'John',
            body: selectedName
          });

          var inputOutput = getExtension(b_obj, 'input:inputOutput');
          if (!inputOutput) {
            inputOutput = moddle.create('input:inputOutput', {
              inputParameters: [ inputParameter ]
            });
            b_obj.extensionElements = b_obj.extensionElements || moddle.create('bpmn:ExtensionElements');
            b_obj.extensionElements.get('values').push(inputOutput);
          }

output of above code is,

  <bpmn2:extensionElements>
    <input:inputOutput inputParameters="[object Object]" />
  </bpmn2:extensionElements>

How I achieve my proper XML format with proper prefix.

Hi :wave: I’m a bit confused by your json model. You define inputOutput two times. Although you define inputParameter as a non-array, but trying to create it as array inside your code.

What can give clarity is to share your setup inside a CodeSandbox and give more details on what you want to achieve.

Hi @Niklas_Kiefer ,
My code is now customized and modular with different files so I can’t able provide a complete code. But I can explain to you what I did. After the drag-and-drop task, I created customize property panel in which there are 3 tabs General, Input, and output. In the Input tab, I created one dropdown. After selecting a value from the dropdown following XML needs to be generated.

      <bpmn:extensionElements>       
        <camunda:inputOutput>
          <camunda:inputParameter name="John">John is very smart</camunda:inputParameter>
        </camunda:inputOutput>
      </bpmn:extensionElements>

I provide you only related code here.
What will be the correct JSON mode? I created meta model using GitHub - bpmn-io/bpmn-js-example-model-extension: An example of creating a model extension for bpmn-js

Thanks for sharing. Seems like you’re trying to set the inputParameters directly in the business object.

b_obj.extensionElements.get(‘values’).push(inputOutput);

I’d recommend you to use commands for that, as shown in the current implementation. This way you can ensure the properties will be properly set + you receive undo/redo support by using commands.

Hi @Niklas_Kiefer , I think all thing jumping from my head. Can you guide me or provide details documentation about how to set meta-model and what should be hierarchy i have to follow to create elements. I have seen the official example GitHub - bpmn-io/bpmn-js-example-model-extension: An example of creating a model extension for bpmn-js . Through this example, I created JSON meta-model but in that example their is not code or description that how to create an element inside other elements e.g.,

          <qa:comment author="Klaus">
            Our operators always have a hard time to figure out, what they need to do here.
          </qa:comment>

Using above example I just learned to create qa:analysisDetails.
Thank you very much for provide me support.

There is probably no example that delivers exactly your use case. Here is a CodeSandbox that is creating “nested” elements. This is also using the camunda moddle descriptors under the hood.

Your use case seems to be very specific with

  • adding a properties panel extension
  • adding a custom meta model
  • creating custom elements inside the properties panel extension
  • … ?

Maybe it would help if you go through this step by step and ask about specific things once you’re struggling on one of these steps

Ok @Niklas_Kiefer Many thanks for your support.
I want exact XML model like below,

      <bpmn:extensionElements>       
        <camunda:inputOutput>
          <camunda:inputParameter name="John">John is very smart</camunda:inputParameter>
        </camunda:inputOutput>
      </bpmn:extensionElements>

So first step I need custom meta-model for this right? So I created meta-model,

{
    "name": "Input",
    "prefix": "input",
    "uri": "http://Input",
    "xml": {
      "tagAlias": "lowerCase"
    },
    "associations": [],
    "types": [
      {
        "name": "StartEvent",
        "extends": [
          "bpmn:Activity",
        ],
        "properties": [
          {
            "name": "output",
            "isAttr": true,
            "isMany": true,
            "type"  : "array"
          },
          {
            "name": "IsStartable",
            "default": true,
            "isAttr": true,
            "type"  : "Boolean"
          }
        ]
      },
      {
        "name": "inputOutput",
        "superClass": ["Element"],
        "properties": [
          {
            "name": "inputOutput",
            "isMany": false,
            "type": "String"
          }
        ]
      },
      {
        "name": "inputParameter",
        "superClass": ["inputOutput"],
        "properties": [
          {
            "name": "name",
            "type": "String",
            "isAttr": true
          },
          {
            "name": "text",
            "isBody": true,
            "type": "String"
          },
        ]
       }
    ]
  }

I’m confused whether I created it correctly or not but my reference point is the official model-extension example.

2nd step my current bpmn UI,

In the above diagram, I created custom tab input and created a dropdown. After selecting a value from a dropdown the camunda:inputOutput and camunda:inputParameter should create. For that I write code in my dropdown set event,

function getExtension(element, type) {
  if (!element.extensionElements) {
    return null;
  }

  return element.extensionElements.values.filter(function(e) {
    return e.$instanceOf(type);
  })[0];
}

export default function(group, element, translate, dropdownOptions, ddName, _id, bpmnFactory, canvas, elementRegistry,) {

  if (is(element, 'bpmn:Activity')) {
    var bo = getBusinessObject(element);
    var attributes = bo.$attrs;
    var values = attributes[_id];
    
      var dropdownBox = entryFactory.selectBox(translate, {
        id: _id,
        label: ddName,
        emptyParameter: false,
        selectOptions: dropdownOptions,
        modelProperty: _id,

        get: function(element, node) {
          return bo;
        },

        set: function setValue(element, values, node) {

          var b_obj = getBusinessObject(element);
          var selectedValues = {};
          selectedValues = values;
          prop[_id] = selectedValues[_id];
          var selectedName = dropdownOptions[parseInt(prop[_id])].name;
          var bo = cmdHelper.updateBusinessObject(element, b_obj, prop);
          var bpmnModel = window.bpnModel;

          var moddle = bpmnModel.get('moddle');

          console.log(selectedName);

          var inputParameter = moddle.create('camunda:InputParameter', {
            name: 'Rajendra',
            body: selectedName
          });

          var inputOutput = getExtension(b_obj, 'camunda:inputOutput');
          if (!inputOutput) {
            inputOutput = moddle.create('camunda:inputOutput');
            b_obj.extensionElements = b_obj.extensionElements || moddle.create('bpmn:ExtensionElements');
            b_obj.extensionElements.get('values').push(inputOutput);
          }

         
          return bo;
        },
      })
      group.entries.push(dropdownBox);
  }
}

so my above code generate XML like below,

  <bpmn2:extensionElements>
    <input:inputOutput inputParameters="[object Object]" />
  </bpmn2:extensionElements>

I’m not 100% sure why you need a custom meta-model here? The XML you’re trying to produce looks exactly the same as from camunda-bpmn-moddle. Or is there a difference from basic Camunda Input / Output?

I need a custom meta-model here because I’m creating custom input and output tabs in the property panel. My requirement is specific to get input from the input tab and showing output in the Output tab. I removed unused existing properties from the property panel.

To clarify: just because you want to build custom input / output tabs, it does not necessarily mean you have to create a custom meta model, especially if you want to re-use the exact same Camunda Input & Output parameters.

1 Like

I got wonderful help from here
The difference only that, I created input:inputOutput using BpmnModeler but instead of I have to create it using bpmnfactory.
@Niklas_Kiefer Thanks a lot for guiding me.