Keep position after importing new data

I’d like to display the data that changes to a 10 second interval on the diagram.

Here’s my code.

var myDiagram = $(go.Diagram, this.$el, {
      layout: $(go.TreeLayout, {
        setsPortSpot: false,
        setsChildPortSpot: false,
        isRealtime: false,
      }),      
      initialDocumentSpot: go.Spot.Center,
      initialViewportSpot: go.Spot.Center,
     
    });

var serviceGroupTemplate = $(
      go.Group,
      "Vertical",
      {
        layout: $(go.GridLayout, {
          wrappingColumn: 5,
          alignment: go.GridLayout.Position,
          cellSize: new go.Size(1, 1),
        }),
      },
      { defaultStretch: go.GraphObject.Horizontal },
      { fromSpot: go.Spot.RightSide, toSpot: go.Spot.LeftSide },
      new go.Binding("location", "loc").makeTwoWay(),  // TwoWay Binding
...
)

var serverGroupTemplate = $(
      go.Group,
      "Vertical",
      {
        layout: $(go.TreeLayout, {
          setsPortSpot: false,
          setsChildPortSpot: false,
        })
      },
      { defaultStretch: go.GraphObject.Horizontal },
      { fromSpot: go.Spot.RightSide, toSpot: go.Spot.LeftSide },
...
)

var serverTemplate = $(
      go.Node,
      "Horizontal",
      { defaultStretch: go.GraphObject.Horizontal },
      { fromSpot: go.Spot.RightSide, toSpot: go.Spot.LeftSide },
...
)

There is a server group in the service group and a server node in the server group.
The problem is that I move the group or node and change to the initial layout 10 seconds later.
I want the group and the node to be in the position I changed in 10 seconds.

I tried with twoway binding, but it dosen’t work

new go.Binding("location", "loc").makeTwoWay(),  // TwoWay Binding

How can I do that?

Layouts are invalidated when a node or a link is added or removed. Set Layout.isOngoing to false on all of your layouts.
https://gojs.net/latest/intro/layouts.html#LayoutInvalidation

I added isOngoing:false to all layouts. As a result, no groups and nodes are displayed…

I do the following every 10 seconds when the data is updated.

updateDiagramFromData: function () {
      this.diagram.startTransaction();
      this.diagram.updateAllRelationshipsFromData();
      this.diagram.updateAllTargetBindings();
      this.diagram.commitTransaction("updated");
    },

Is this wrong?

For your information, I am using the vue.js framework.

Layout.isOngoing controls whether adding or removing nodes or links, or the changing of the size of nodes, will cause a layout to happen again. If neither a layout nor your data provide a real location for a node, there won’t be any place to draw the node.

However, you can specify more specific conditions under which a layout does happen, and when the layout is not invalidated. Those are controlled by the Part.layoutConditions property, a set of flags. They are discussed at that Introduction page that you have read:
https://gojs.net/latest/intro/layouts.html#LayoutInvalidation
And there are a few samples that make use of those flags.

Hi, there!

I gave up before, but I want to try it again.

I solved that problem with
isOngoing=false
and
new go.Binding(“position”, “pos”, go.Point.parse).makeTwoWay(go.Point.stringify)

but, now I have another problem.


I expected it to look like this… but when I add isOngoing = false option,
It looks like below…

I’ve set { defaultStretch: go.GraphObject.Horizontal } to Group object
and { minSize: new go.Size(450, NaN) } to Panel

Is there an association between isOngoing and defaultStretch?

I don’t have enough information to say anything. What do your screenshots show? What are their templates? If they are Groups, what and where are their members?

var serviceGroupTemplate = $(
      go.Group,
      "Vertical",
      {
        layout: $(go.GridLayout, {
          wrappingColumn: 5,
          alignment: go.GridLayout.Position,
          cellSize: new go.Size(1, 1),
        }),
      },
      { defaultStretch: go.GraphObject.Horizontal },
      { fromSpot: go.Spot.RightSide, toSpot: go.Spot.LeftSide },
      new go.Binding("position", "pos", go.Point.parse).makeTwoWay(go.Point.stringify),
      $(
        go.Panel,
        "Auto",
        $(go.Shape, "Rectangle", {
          fill: "#36a3f7",
          stroke: "#36a3f7",
        }),
        ...
        ),
        $(
        go.Panel,
        "Auto",
        $(go.Shape, "Rectangle", {
          fill: "white",
          stroke: "#36a3f7",
          strokeWidth: 2,
        }),
        $(go.Placeholder, { padding: 20 }),
        $(
          go.Shape,
          {
            visible: false,
            width: 10,
            height: 10,
            alignment: new go.Spot(0.5, 1, 0, -3),
            alignmentFocus: go.Spot.Bottom,
          },
          new go.Binding("visible", "loop")
        )
      )

This is part of my code.
I have Service group(Group), Server group(Group), Server(Node).
service group contains server group, and server group contains server.
This code is for the service group.
Screenshots are first panel of serviceGroupTemplate.
I want the width of the panel to be the same as the panel below.

Here is what I tried when using your group template code:

    myDiagram.groupTemplate =
      $(go.Group, "Vertical",
        {
          layout: $(go.GridLayout, {
            wrappingColumn: 5,
            alignment: go.GridLayout.Position,
            cellSize: new go.Size(1, 1),
          }),
        },
        { defaultStretch: go.GraphObject.Horizontal },
        { fromSpot: go.Spot.RightSide, toSpot: go.Spot.LeftSide },
        new go.Binding("position", "pos", go.Point.parse).makeTwoWay(go.Point.stringify),
        $(go.Panel, "Auto",
          $(go.Shape, "Rectangle", {
            fill: "#36a3f7",
            stroke: "#36a3f7",
          }),
          //...
          $(go.TextBlock, { margin: new go.Margin(5, 5, 3, 5) }, new go.Binding("text")),
          $("Button", { alignment: go.Spot.Right }, $(go.Shape, { fill: "white", width: 16, height: 16 }))
        ),
        $(go.Panel, "Auto",
          $(go.Shape, "Rectangle", {
            fill: "white",
            stroke: "#36a3f7",
            strokeWidth: 2,
          }),
          $(go.Placeholder, { padding: 20 }),
          $(go.Shape,
            {
              visible: false,
              width: 10,
              height: 10,
              alignment: new go.Spot(0.5, 1, 0, -3),
              alignmentFocus: go.Spot.Bottom,
            },
            new go.Binding("visible", "loop")
          )
        )
      );

I had to put in something in the “Auto” Panel header, so I included a TextBlock and a blank “Button”.

This worked well, as you can see:

Did you try adding the isOngoing=false option as well?

var myDiagram = $(go.Diagram, this.$el, {
      layout: $(go.TreeLayout, {
        isOngoing: false,
        isInitial: false,
      }),
      initialContentAlignment: go.Spot.TopLeft,
      "animationManager.isEnabled": false,      
    });

There is no problem when isOngoing is set to true. The problem is when it is false

Here’s what I have:

<!DOCTYPE html>
<html>
<head>
  <title>Minimal GoJS Editor</title>
  <!-- Copyright 1998-2021 by Northwoods Software Corporation. -->
  <script src="go.js"></script>
  <script id="code">
    function init() {
      var $ = go.GraphObject.make;

      myDiagram =
        $(go.Diagram, "myDiagramDiv",
          {
            layout: $(go.TreeLayout, { isRealtime: false, isOngoing: false }),
            "undoManager.isEnabled": true
          });

      myDiagram.nodeTemplate =
        $(go.Node, "Auto",
          { locationSpot: go.Spot.Center },
          new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
          $(go.Shape,
            {
              fill: "white", stroke: "gray", strokeWidth: 2,
              portId: "", fromLinkable: true, toLinkable: true,
              fromLinkableDuplicates: true, toLinkableDuplicates: true,
              fromLinkableSelfNode: true, toLinkableSelfNode: true,
              fromSpot: go.Spot.Right, toSpot: go.Spot.Left
            },
            new go.Binding("stroke", "color")),
          $(go.TextBlock,
            {
              margin: new go.Margin(5, 5, 3, 5), font: "10pt sans-serif",
              minSize: new go.Size(16, 16), maxSize: new go.Size(120, NaN),
              editable: true
            },
            new go.Binding("text").makeTwoWay())
        );

    myDiagram.groupTemplate =
      $(go.Group, "Vertical",
        {
          layout: $(go.GridLayout, {
            isOngoing: false,
            wrappingColumn: 5,
            alignment: go.GridLayout.Position,
            cellSize: new go.Size(1, 1),
          }),
        },
        { defaultStretch: go.GraphObject.Horizontal },
        { fromSpot: go.Spot.RightSide, toSpot: go.Spot.LeftSide },
        new go.Binding("position", "pos", go.Point.parse).makeTwoWay(go.Point.stringify),
        $(go.Panel, "Auto",
          $(go.Shape, "Rectangle", {
            fill: "#36a3f7",
            stroke: "#36a3f7",
          }),
          //...
          $(go.TextBlock, { margin: new go.Margin(5, 5, 3, 5) }, new go.Binding("text")),
          $("Button", { alignment: go.Spot.Right }, $(go.Shape, { fill: "white", width: 16, height: 16 }))
        ),
        $(go.Panel, "Auto",
          $(go.Shape, "Rectangle", {
            fill: "white",
            stroke: "#36a3f7",
            strokeWidth: 2,
          }),
          $(go.Placeholder, { padding: 20 }),
          $(go.Shape,
            {
              visible: false,
              width: 10,
              height: 10,
              alignment: new go.Spot(0.5, 1, 0, -3),
              alignmentFocus: go.Spot.Bottom,
            },
            new go.Binding("visible", "loop")
          )
        )
      );

      load();
    }

    // save a model to and load a model from Json text, displayed below the Diagram
    function save() {
      var str = myDiagram.model.toJson();
      document.getElementById("mySavedModel").value = str;
    }
    function load() {
      var str = document.getElementById("mySavedModel").value;
      myDiagram.model = go.Model.fromJson(str);
    }
    </script>
</head>
<body onload="init()">
  <div id="myDiagramDiv" style="width: 100%; height: 400px; border: solid 1px black"></div>
  <div id="buttons">
    <button id="loadModel" onclick="load()">Load</button>
    <button id="saveModel" onclick="save()">Save</button>
  </div>
  <textarea id="mySavedModel" style="width:100%;height:200px">
{ "class": "GraphLinksModel",
  "nodeDataArray": [
{"text":"Group 1","color":"purple","isGroup":true,"key":-5},
{"text":"Group 2","color":"purple","isGroup":true,"key":-2},
{"text":"red node","color":"red","key":-1,"group":-5},
{"text":"green node","color":"green","key":-4,"group":-5},
{"text":"blue node","color":"blue","key":-3,"group":-2},
{"text":"orange node","color":"orange","key":-6,"group":-2},
{"text":"Group 3","color":"purple","isGroup":true,"key":-7,"group":-2},
{"text":"green node","color":"green","key":-8,"group":-7}
  ],
  "linkDataArray": [
{"from":-1,"to":-4},
{"from":-3,"to":-6}
  ]}
  </textarea>
</body>
</html>

I tried adding interval to your code

function init() {
      var $ = go.GraphObject.make;

      myDiagram =
        $(go.Diagram, "myDiagramDiv",
          {
            layout: $(go.TreeLayout, { isRealtime: false, isOngoing: false }),
            "undoManager.isEnabled": true
          });

      myDiagram.nodeTemplate =
        $(go.Node, "Auto",
          { locationSpot: go.Spot.Center },
          new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
          $(go.Shape,
            {
              fill: "white", stroke: "gray", strokeWidth: 2,
              portId: "", fromLinkable: true, toLinkable: true,
              fromLinkableDuplicates: true, toLinkableDuplicates: true,
              fromLinkableSelfNode: true, toLinkableSelfNode: true,
              fromSpot: go.Spot.Right, toSpot: go.Spot.Left
            },
            new go.Binding("stroke", "color")),
          $(go.TextBlock,
            {
              margin: new go.Margin(5, 5, 3, 5), font: "10pt sans-serif",
              minSize: new go.Size(16, 16), maxSize: new go.Size(120, NaN),
              editable: true
            },
            new go.Binding("text").makeTwoWay())
        );

    myDiagram.groupTemplate =
      $(go.Group, "Vertical",
        {
          layout: $(go.GridLayout, {
            isOngoing: false,
            wrappingColumn: 5,
            alignment: go.GridLayout.Position,
            cellSize: new go.Size(1, 1),
          }),
        },
        { defaultStretch: go.GraphObject.Horizontal },
        { fromSpot: go.Spot.RightSide, toSpot: go.Spot.LeftSide },
        new go.Binding("position", "pos", go.Point.parse).makeTwoWay(go.Point.stringify),
        $(go.Panel, "Auto",
          $(go.Shape, "Rectangle", {
            fill: "#36a3f7",
            stroke: "#36a3f7",
          }),
          //...
          $(go.TextBlock, { margin: new go.Margin(5, 5, 3, 5) }, new go.Binding("text")),
          $("Button", { alignment: go.Spot.Right }, $(go.Shape, { fill: "white", width: 16, height: 16 }))
        ),
        $(go.Panel, "Auto",
          $(go.Shape, "Rectangle", {
            fill: "white",
            stroke: "#36a3f7",
            strokeWidth: 2,
          }),
          $(go.Placeholder, { padding: 20 }),
          $(go.Shape,
            {
              visible: false,
              width: 10,
              height: 10,
              alignment: new go.Spot(0.5, 1, 0, -3),
              alignmentFocus: go.Spot.Bottom,
            },
            new go.Binding("visible", "loop")
          )
        )
      );

      load();
      interval();
    }

    // save a model to and load a model from Json text, displayed below the Diagram
    function save() {
      var str = myDiagram.model.toJson();
      document.getElementById("mySavedModel").value = str;
    }
    function load() {
      var str = document.getElementById("mySavedModel").value;
      myDiagram.model = go.Model.fromJson(str);
    }
    function interval() {
      setInterval(() => {
        load()
      }, 5000)
    }

After load() every 5 seconds, it returns to the original position. Like below

How can the group stay where I am after I move?

Each call to load will restore the initial state of the diagram. Or is the model different each time? That seems a very inefficient thing to do. Ideas: https://gojs.net/latest/intro/usingModels.html#ModifyingModels
Also: https://gojs.net/latest/intro/layouts.html#LayoutInvalidation