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.