- How does your custom properties for the user tasks look like? Cf. moddle descriptors
They are in the screencap in the original post. My moddle descriptor is the camunda-bpmn-moddle/resources/camunda.json The “caminda:property” is I guess this:
{
"name": "Property",
"superClass": [
"Element"
],
"properties": [
{
"name": "id",
"type": "String",
"isAttr": true
},
{
"name": "name",
"type": "String",
"isAttr": true
},
{
"name": "value",
"type": "String",
"isAttr": true
}
]
},
The properties are being read by the Properties Panel if the diagram is saved and reopened, which I guess points that it’s not a problem of unrecognized custom properties.
- You’re speaking from drag&drop: how is your custom palette provider look like?
I am dragging items not from a custom palette (although I’ve customized the palette to hide some things from it) but from a list outside of the diagram parent element.
The list of draggable items is returned from an API response, and when dragging begins, the elements receive their diagram-compatible shape.
A draggable list item looks like this in the template:
<mat-tree-node
class="leaf-node"
[class.is-on-diagram]="node.isOnDiagram"
*matTreeNodeDef="let node"
[draggable]="!node.isOnDiagram"
(dragstart)="dragStartHandler($event, node)"
[matTooltip]="node.isOnDiagram ? 'Already used on the diagram' : ''">
<fa-icon class="leaf-icon" leaf icon="grip-lines"></fa-icon>
<span class="leaf-title">{{node.name}}</span>
</mat-tree-node>
And on a dragStart event, this is the dragStartHandler() function definition:
dragStartHandler(dragEvent: DragEvent, element: ElementDefinition) {
const definition = `{
"type": "bpmn:${element.camundaActivityType}",
"name": "${element.name.replace('\\', '\\\\')}",
"bpmnActivityId": "${element.bpmnActivityId}",
"calledElement": "${element.calledElement}",
"calledProcessId": "${element.calledProcessId}"
}`;
const bpmnDefinition = JSON.parse(definition);
const elementFactory = this.bpmnService.getElementFactory();
const initialShape = elementFactory.createShape(bpmnDefinition);
const create = this.bpmnService.getCreate();
if (bpmnDefinition.type === 'bpmn:CallActivity') {
this.bpmnService.addExtensionElements(
initialShape, element, bpmnDefinition).subscribe((diagramElement) => {
create.start(dragEvent, diagramElement);
});
} else {
const diagramElement = this.bpmnService.generateDiagramElement(initialShape, element, bpmnDefinition);
create.start(dragEvent, diagramElement);
}
}
Hopefully I’ll be able to show you all this in action in the workshop today.
For user tasks, the bpmnService.generateDiagramElement() would be called, which will generate the js object useful for the diagram, in accordance with the bpmnDefinition which is provided, along with the custom properties. Here is how this function looks:
public generateDiagramElement(elementShape, diagramElement: ElementDefinition, bpmnDefinition) {
const newExtensionElements = this.moddle.create('bpmn:ExtensionElements');
newExtensionElements.values = [];
const suppliedVariables = [...diagramElement.workflowVariables];
const newProperties = this.moddle.createAny('camunda:properties');
newProperties.$children = [];
const suppliedProperties = [...diagramElement.workflowProperties];
suppliedVariables.forEach(variable => {
const newVariable = this.moddle.createAny('camunda:in');
if (variable.name === 'businessKey') {
newVariable.businessKey = variable.value;
} else {
newVariable.target = variable.name;
newVariable.sourceExpression = variable.value;
}
newExtensionElements.values.push(newVariable);
});
suppliedProperties.forEach(property => {
const newProperty = this.moddle.createAny('camunda:property');
newProperty.name = property.name;
newProperty.value = property.value;
newProperties.$children.push(newProperty);
});
newExtensionElements.values.push(newProperties);
this.modeling.updateProperties(elementShape, {
extensionElements: newExtensionElements,
});
elementShape.businessObject.name = bpmnDefinition.name;
elementShape.businessObject.id = bpmnDefinition.bpmnActivityId;
elementShape.businessObject.calledElement = bpmnDefinition.calledElement;
return elementShape;
}