I can programmatically copy and paste subprocesses from an XML-template as discussed in Programmatically populate collapsed subprocess from XML using
import inherits from 'inherits';
import { is } from 'bpmn-js/lib/util/ModelUtil';
import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor';
import subProcessTemplates from './SubProcessTemplates.bpmn';
import BpmnModeler from 'bpmn-js/lib/Modeler';
function ifNewResourceActivity(fn) {
return function(event) {
var context = event.context,
element = context.shape;
if ( (event.command == 'shape.create' || event.command == 'shape.resize') && is(element, 'bpmn:SubProcess') &&
( element.businessObject.type == 'Resource' || element.businessObject.type == 'Request' || element.businessObject.type == 'Release' )
) {
fn(event);
}
};
}
let children = {};
function selectChildren(elementRegistry, id) {
const elements = elementRegistry.getAll().filter(function(element) {
// determine children to be copied
return element.parent && element.parent.id == id + '_plane';
});
return elements;
}
const subProcessModeler = new BpmnModeler();
subProcessModeler.importXML(subProcessTemplates).then( function() {
const sourceClipboard = subProcessModeler.get('clipboard'),
sourceCopyPaste = subProcessModeler.get('copyPaste'),
sourceElementRegistry = subProcessModeler.get('elementRegistry');
// copy resource template
sourceCopyPaste.copy(selectChildren(sourceElementRegistry,'ResourceActivityTemplate'));
// retrieve clipboard contents
children['Resource'] = sourceClipboard.get();
// copy request template
sourceCopyPaste.copy(selectChildren(sourceElementRegistry,'RequestActivityTemplate'));
// retrieve clipboard contents
children['Request'] = sourceClipboard.get();
// copy release template
sourceCopyPaste.copy(selectChildren(sourceElementRegistry,'ReleaseActivityTemplate'));
// retrieve clipboard contents
children['Release'] = sourceClipboard.get();
});
function preventResize(evt) {
evt.context.newBounds = { x: evt.context.shape.x, y: evt.context.shape.y, width: evt.context.shape.width, height: evt.context.shape.height };
}
/**
* A handler responsible for creating children to a resource subprocess when this is created
*/
export default function ResourceUpdater(eventBus, modeling, elementFactory, elementRegistry, editorActions, contextPad, dragging, directEditing) {
CommandInterceptor.call(this, eventBus);
function createChildren(evt) {
const context = evt.context,
element = context.shape,
businessObject = element.businessObject;
const targetClipboard = modeler.get('clipboard'),
targetCopyPaste = modeler.get('copyPaste'),
targetElementRegistry = modeler.get('elementRegistry');
// put into clipboard
targetClipboard.set(children[businessObject.type]);
const pasteContext = {
element,
point: {x:0, y:0}
};
//console.log("PASTE",pasteContext);
// paste tree
targetCopyPaste.paste(pasteContext);
}
this.preExecute([
'shape.resize'
], ifNewResourceActivity(preventResize));
this.postExecute([
'shape.create'
], ifNewResourceActivity(createChildren));
/// other stuff ...
}
inherits(ResourceUpdater, CommandInterceptor);
ResourceUpdater.$inject = [ 'eventBus', 'modeling', 'elementFactory', 'elementRegistry', 'editorActions', 'contextPad', 'dragging', 'directEditing' ];
However, extensionElements
within the XML-template are not copied. From Change type of element but keep already set properties - #2 by philippfromme I learned that extensionElements
are not copied by default and I tried adding this
eventBus.on('moddleCopy.canCopyProperty', function(context) {
var property = context.property;
if (is(property, 'bpmn:ExtensionElements')) {
return property;
}
});
which appears to somehow work, but not completely. With this added code, the extensionElements
are actually included within the target model and I can see them within the saved XML. If I reload the saved model, everything works as intended and I can see the extensionElements
content in my properties panel. However, without reloading I cannot see the content in the properties panel.
@philippfromme Any idea on what is wrong? Do I need to clone property
before returning (how can this be done?), do I need to trigger an update of the respective element or business object (how could this be done?), or could it be that the problem is within the properties panel. I’d be happy to share further code if needed to understand the issue. Thanks for any help on this!