Reload Diagram Link is not the same

Hi

I got a problem when reload the diagram. It allows user to change node position. And when user click save, I currently save the node position (x,y).

Then when user enter again, it will load the node positions and init the diagram. But the problem is the the Link does not look the same.

Below is how I init the node with its positions:

let offlinePosition = vm.position.nodePosition;

  for (let i = 0; i < vm.uniqueNodes.length; i++) {
    let item = vm.uniqueNodes[i];
    // let topArray = [];
    let obj = {
      "key": i,
      "text": item,
    };

    _.map(linkDataArray, function (n) {
      if (n.from == i) {
        // topArray.push({"portColor": "#14abef", "portId": n.fromPort});
        obj.node = n.fromNode;
        obj.opacityNumber = n.opacity;
      }
      if (n.to == i) {
        // topArray.push({"portColor": "#14abef", "portId": n.toPort});
        obj.node = n.toNode;
        obj.opacityNumber = n.opacity;
      }
    });

    if (offlinePosition && offlinePosition[obj.node.SysId]) {
      obj["pos"] = offlinePosition[obj.node.SysId];
    }

    obj.category = addCategory(obj);

    // obj.topArray = topArray;

    nodeDataArray.push(obj);
  }

  vm.chartData = {
    "nodeDataArray": nodeDataArray,
    "linkDataArray": linkDataArray
  }

Thank you in advance !!!

If the exact route for each Link is important to you, are you saving the Link.points property with a TwoWay Binding?
new go.Binding("points").makeTwoWay()

Hi walter,

Thank you for replying me :)

I already set the TwoWay binding for it:

myDiagram.linkTemplate =
    $(go.Link,
      {routing: go.Link.AvoidsNodes, curve: go.Link.JumpGap, corner: 10},
      new go.Binding("points").makeTwoWay(),
      $(go.Shape, {isPanelMain: true, strokeWidth: 8},
        new go.Binding("stroke", "isHeating", function (b) {
          if (b) {
            return "red";
          } else {
            return "#add8e6";
          }
        }))
    );

And here is how I get and save the points belong to links

function getDiagramPosition() {
  let nodeIterator = myDiagram.nodes.iterator;
  let linkIterator = myDiagram.links.iterator;      
  let nodePosition = {};
  let linkPosition = {};

  // get node position
  while (nodeIterator.next()) {
    let node = nodeIterator.value;
    nodePosition[node.data.node.SysId] = node.position.x + " " + node.position.y;
  }
  
  // get link position
  while (linkIterator.next()) {
    let link = linkIterator.value;
    let pointIterator = link.points.iterator;
    let points = [];

    while (pointIterator.next()) {
      let point = pointIterator.value;
      points.push(point.x);
      points.push(point.y);
    }
    linkPosition[link.fromNode.data.node.SysId + "-" + link.toNode.data.node.SysId] = points;
  }

  return {nodePosition, linkPosition};
}

And here is how I set again points on the links

for (let i = 0; i < vm.rawData.length; i++) {
    let item = vm.rawData[i];
    let index1 = vm.uniqueNodes.indexOf(item.node1);
    let index2 = vm.uniqueNodes.indexOf(item.node2);
    let points = linkPosition[item.raw.endNode1.SysId + "-" + item.raw.endNode2.SysId];
    for (let j = 0; j < points.length; j++) {
      points[j] = +points[j];
    }

    linkDataArray.push({
      from: index1,
      to: index2,
      fromNode: item.raw.endNode1,
      toNode: item.raw.endNode2,
      isHeating: item.raw.isHeating == 'true',
      opacity: item.raw.opacity,
      points: points
    });
  }

But the result is wrong. The node has correct position, but it looks like it has some offset for the links

Thank you,
Marcus

Are you using Model.toJson and Model.fromJson? If so, you don’t need to do any of your code, because the data.points property will be saved and loaded for you automatically.

Take a look at any of the samples that have new go.Binding("points").makeTwoWay() and that support saving and loading the model.

Even if you are doing your own serialization, the information that you need is already in the link data, as the data.points property, whose information you need to persist faithfully.

It works ;-)

I don’t know why the data is different between this:

let nodeIterator = myDiagram.nodes.iterator;
let linkIterator = myDiagram.links.iterator; 

and this:

const model = JSON.parse(myDiagram.model.toJson());
nodePosition = model.nodeDataArray;
linkPosition = model.linkDataArray;

Anyway, it is working now :) Thank you alot

Hello,

More to this topic. When storing node locations and link points to JSON, using Binding with makeTwoWay for nodes and links and restoring them and use ForcedDirectedLayout I see a diagram links are restored properly, however the nodes aren’t in proper places. When no using any layout, all works fine. Is it a bug in GoJS?

I suspect you have a conflict – you are setting the node locations via a Binding on the Node.location property from some property on the node data object in the model, and you are setting node locations via the ForceDirectedLayout that is the value of Diagram.layout.

If you do not want the layout to be performed when the model is loaded, you should set Layout.isInitial to false.

1 Like

walter,

This is exactly what happened. Thanks for your valuable reply. Now it works exactly as required, when a saved diagram loaded, all the nodes and links are properly positioned. When a new diagram is being build, the layout is applied to position nodes. Thanks again.