Adding a node by dragging over a connector
nautilebleu opened this issue · comments
Hi,
We are trying to setup a bot builder using Vue and Syncfusion Diagram.
We encounter some strange behaviours when developping the drag and drop
functionnality.
Currently, we are able to add nodes by dragging them from the palettes on
another node. It successfully adds the node to the diagram and triggers a
relayout of the diagram using the following code (which is called on the drop
event:
insertNewNode (src: NodeModel, target: NodeModel) {
const diagram = this.diagram;
(src as any).inEdges = [target.id]
this.$nextTick(() => {
const connector = {
id: 'connector' + Math.floor(Math.random() * 1000 + 100),
sourceID: (target as any).id,
targetID: src.id,
Id: Math.floor(Math.random() * 1000 + 100)
}
const diag: any = diagram
diag.add(connector)
diag.doLayout()
this.$store.dispatch('botBuilder/buildNodesFromDiagram', diagram)
})
}
Everything is ok, the whole diagram is reorganised as needed.
We also allows to move a subtree to another node with the following code (once
again, called from the drop
event):
moveToNewParent (src: NodeModel, target: NodeModel) {
const diagram = this.diagram;
(src as any).parentUuid = (target.data as any).customData.uuid
let conn
(src as any).inEdges.forEach((connectorId: any) => {
diagram.connectors.forEach((connector: { id: any }) => {
if (connector.id === connectorId) {
conn = connector
}
})
})
diagram.remove(conn)
this.$nextTick(() => {
const connector = {
id: 'connector' + Math.floor(Math.random() * 1000 + 100),
sourceID: target.id,
targetID: src.id,
Id: Math.floor(Math.random() * 1000 + 100)
}
diagram.add(connector)
diagram.doLayout()
this.$store.dispatch('botBuilder/buildNodesFromDiagram', diagram)
})
}
This code also leads to the desired behavior, and the whole tree is reorganised
as expected on the diagram.
When we try to do the same when dropping a node over a connector with the
following code:
insertOnConnector (src: NodeModel, target: ConnectorModel) {
const diagram = this.diagram
const connectorId = (target.properties.wrapper as any).id
let parentNode: Node | null = null
let childNode: Node | null = null
diagram.nodes.forEach((node: any) => {
if (node.outEdges.includes(connectorId)) {
parentNode = node
} else if (node.inEdges.includes(connectorId)) {
childNode = node
}
})
if (parentNode && childNode) {
const pNodeOutEgdes: Array<string> = (parentNode as any).outEdges
const cNodeOutEgdes: Array<string> = (childNode as any).outEdges
pNodeOutEgdes.splice(pNodeOutEgdes.indexOf(connectorId), 1)
cNodeOutEgdes.splice(cNodeOutEgdes.indexOf(connectorId), 1)
diagram.remove(target)
this.$nextTick(() => {
const diag: any = diagram
const connectorParent = {
id: 'connector' + Math.floor(Math.random() * 1000 + 100),
sourceID: (parentNode as any).id,
targetID: src.id,
Id: Math.floor(Math.random() * 1000 + 100)
}
diag.add(connectorParent)
this.$nextTick(() => {
diag.doLayout()
})
const connectorChild = {
id: 'connector' + Math.floor(Math.random() * 1000 + 100),
sourceID: src.id,
targetID: (childNode as any).id,
Id: Math.floor(Math.random() * 1000 + 100)
}
diag.add(connectorChild)
this.$nextTick(() => {
diag.doLayout()
})
})
}
}
It works only to reorganize the diagram if we add the node on the connector of
a leaf node. If we do this on a connector that is linked to a node with several
children (and grand children), it doesn't trigger the relayout and the new node
is placed over the next one.
We tried to use the refresh
method instead of doLayout
but:
- if we call it without a
clear
before, it adds another tree next to the
previous version. - if we call it with
clear
before, it adds another tree next to the
previous version, it rerenders only the old version.
We also try to use refreshDiagram
method: it works quite good, except that
it leaves some glitches of the previous nodes' positions (mostly the text zone
within a node we use to display the preview of the node's content.) Also
sometimes the diagram nodes can't be dragged anymore (but new nodes can be
added)
Can you help us finding what we are doing wrong?
Hi Nautilebleu,
On the further analysis of the shared details, we understood that you want to drag and drop a node on a connector in the layout and add the new node in between the source node and target node of the dropped connector. Please refer to the following sample for how to add a new node in between the source node and target node of the dropped connector. We have enabled allowDrop constraints to all the nodes and connectors, so whenever we drag a node from palette and drop on a connector the drop event of diagram will triggers, in the event we have removed the target connector and add the new node and add two connector and then called the doLayout API to arrange the new node and connector based on the automatic layout algorithm.
Code snippet:
drop: (args) => {
// canceled the addition of dropped node
args.cancel = true;
if(args.element && args.target && args.target.sourceID && args.target.targetID)
{
var parentNode = args.target.sourceID;
var childNode = args.target.targetID;
// remove the target connector
diagramInstance.remove(args.target);
// add the dropped node and connector using add API
var addedNode = diagramInstance.add({shape:args.element.shape, offsetX:args.element.offsetX,offsetY:args.element.offsetY,
width:args.element.width,height:args.element.height});
diagramInstance.add({
id: 'connector' + Math.floor(Math.random() * 1000 + 100),
sourceID: parentNode,
targetID: addedNode.id,
Id: Math.floor(Math.random() * 1000 + 100)
});
diagramInstance.add({
id: 'connector' + Math.floor(Math.random() * 1000 + 100),
sourceID: addedNode.id,
targetID: childNode,
Id: Math.floor(Math.random() * 1000 + 100)
});
// call the doLayout API to arrange the added node and connectors
diagramInstance.doLayout();
}
},
Sample link: https://www.syncfusion.com/downloads/support/directtrac/general/ze/drapAnNodeOnConnectorInLayout1138290881.zip
Video link: https://www.syncfusion.com/downloads/support/directtrac/general/ze/DropNode_toConnector372519908.zip
If we misunderstood your requirement, please share us more details or replicate the issue in the shared sample. This will be helpful for us to proceed further.
Regards,
Kamesh R.
Thanks for your answer.
We found a solution in the meantime but it's always good to have an official answer