I have enabled ej.diagrams.NodeConstraints.AllowDrop , so that I can reposition a node within diagram container. I am trying to capture the final position of this node after the node is dragged with the diagram container.
To do this , I am using
positionChange: function (args) { ...} and storing the offsetX = args.newValue.offsetX and
,offsetY = args.newValue.offsetY against the node's unique id in a json object.
After this when I am reloading the diagram , I am calling diagram.destroy() and recreating the diagram with json data which I get back on load event.
but while reloading the diagram , the node , which was dragged from it's default to user defined position it's retaining it's default position.
dataSourceSettings: {
..
dataManager: new ej.data.DataManager(workflowData),
doBinding: function (node, data, diagram) {
node.id = data.Key;
node.addInfo = { "Type": nodeType, "UId": data.Id};
node.height = getNodeHeight( nodeType );
node.width = getNodeWidth( nodeType );
node.constraints = CanvasDefaults.TaskNodeConstraints;
node.shape =
{
type: 'HTML',
content: nodeTemplate
};
node.OffsetX = userdefinedPosition.OffsetX,
node.OffsetY =
userdefinedPosition
.OffsetY,
}
}
userdefinedPosition .OffsetX and userdefinedPosition.OffsetY is a global object holds the newposition.offsetX and offsetY which I had captured earlier on positionchange event.
But this is not working.
Q1. Can you please help me figure out what how to capture the final position of a node after user moves it within diagram container, and I also want to use that information to set the offsetX and offsetY when I recreate the diagram, so that those nodes appear in it's user defined position
Q2. since position change gets triggered all along the movement, is there drag end like event which gives me the final coordinates? I have tried drop/dragend, none of them works. The reason could be these events are supposed to get triggered when we drag something from pallet to diagram, but here I am only trying to change it's position within container.
We rendered a sample for node stay its user defined position while load the diagram. Refer to the below-mentioned code example and sample.
Code Example
document.getElementById('RetrivePosition').onclick = function () { var diagramData = { offsetX : "nodeOffsetX", offsetY : "nodeOffsetY" }; localStorage.setItem("file", diagramData); JSON.stringify(localStorage.getItem("file")); }; |
Sample:
Hi Bala -
Thanks for the example, when the node is associated with other nodes through connector, will this work? if bind the node while loading with the new offsetX and offsetY, it apparently holds it's old(default) position. Do I need to override the connector default as well?
if yes, could you please provide me with an example on what properties of the connectors need to be overridden to retain the node in its user defined position.
We have created a sample for your requirement. By using the node inEdges and outEdges property we can be able to get the connector connected to node. After get the inEdges through diagram getObject method we can able to get the connector from node. By using the connector’s sourcePoint and targetPoint method we can able to get the connector points and store it in JSON. Refer to the below-mentioned code example and sample.
Code Example
function positionChange(args) { if (args.state == 'Completed') { nodeOffsetX = args.newValue.offsetX; nodeOffsetY = args.newValue.offsetY; if(args.source.inEdges.length > 0 || args.source.outEdges.length > 0){ var connector = args.source.inEdges.length ? diagram.getObject(args.source.inEdges[0]) : diagram.getObject(args.source.outEdges[0]); connectorSourcePoint = connector.sourcePoint; connectorTargetPoint = connector.targetPoint; } } } document.getElementById('RetrivePosition').onclick = function () { var diagramData = { offsetX : "nodeOffsetX", offsetY : "nodeOffsetY", sourcePoint: "connectorSourcePoint", targetPoint: "connectorTargetPoint" }; localStorage.setItem("file", diagramData); JSON.stringify(localStorage.getItem("file")); }; |
Sample:
https://stackblitz.com/edit/nbdixb-qsyklp?file=index.html,index.js |
I have tried to set the offsetX, offsetY for the node and target and source position of all the inner and outer Edges associated.
When I am loading the screen, I am using doBinding to bind the diagram with data provided to dataManager .
and for every data in nodeModel , I am applying the offsetx/Y and trying to override it's default position.
Also in the getConnectorDefaults , I am trying to override the source and targetPoints for inner and outerEdges. Still it doesn't work. Attached some code snippet for reference.
Attachment: Diagram_6b37380d.zip
2. Also- I saw some relevant article on an api "moveNode" ? can you please share some example
code on how to move a node along with it's connectors?
We modified a sample to achieve your requirement. We retrieved the last changed node position in position Change event and store it in local storage and in created event we update the node position by collecting the data from local storage. Also the connector get moves along with the node after changes. Please refer to the below sample for your reference.
Code snippet
created: function () { diagram.fitToPage({ mode: 'Width' }); jsondata = JSON.parse(localStorage.getItem('file')); if (jsondata != undefined) { if (diagram.nodes) { for (var i = 0; i < diagram.nodes.length; i++) { if (diagram.nodes[i].data.Name == jsondata.Name) { diagram.nodes[i].offsetX = jsondata.offsetX; diagram.nodes[i].offsetY = jsondata.offsetY; diagram.dataBind(); } } } } },
function positionChange(args) { if (args.state == 'Completed') { nodeOffsetX = args.newValue.offsetX; nodeOffsetY = args.newValue.offsetY; nodeName = args.source.data.Name; nodeCollection.offsetX = nodeOffsetX; nodeCollection.offsetY = nodeOffsetY; nodeCollection.Name = nodeName; } localStorage.setItem('file', JSON.stringify(nodeCollection)); jsondata = JSON.parse(localStorage.getItem('file')); } |
Sample
Thanks - for your response, I have tried to implement the example you have sent in my code, here the diagram is already rendered in UI(created) and after that we are manipulating the offsets of the node, in this way even for a split second I can still see the nodes in its default position and then it transitions back to its user defined position. This makes the user experience odd, and it seems like the entire canvas is a bit jerky just after loading. Can't I set the offsets of the node while doing doBinding:
function (nodeModel, data, diagram) {
nodeModel.id = data.Key;
nodeModel.addInfo = { "TaskType": taskType, "UniqueId": data.UniqueId };
nodeModel.height = getNodeHeight(taskType);
nodeModel.width = getNodeWidth(taskType);
nodeModel.constraints = CanvasDefaults.TaskNodeConstraints;
nodeModel.shape =
{
type: 'HTML',
content: nodeTemplate
};
nodeModel.annotations = [
{
constraints: ej.diagrams.AnnotationConstraints.ReadOnly,
}
];
positionNodesInUserDefinedPosition();
}
or in some other way can I set it , before rendering the image?
I see that we can still set the offsetX,offsetY for nodes, and it works when it's not associated with any connector, but for nodes with connectors setting the offsetX,offsetY doesn't work.
Also, not sure if this is not working for me since I am using a html template as node.shape
Hi Sourangsu,
We will validate and update you with more details on Feb 15, 2023.
Regards,
Gobinath
We save the last interacted node position in positionChange event and at initial loading, the created event triggers in which we set the position for last changed node. Similarly, you can set the node position in the created event. Please refer to the sample below for your reference.
Sample
https://stackblitz.com/edit/8girl6-hznguo?file=index.html,index.js
But Is this any different compared to last response posted in this thread on February 9, 2023 06:21 PM?
The difference is we modified the sample on FEB 14 update, your requirements were not met by the attached sample on February 9