How to keep tree roots at original locations

Ok, thank you for your answer. I have a last question regarding layouts.

Is it possible to make multiple tree layouts in the same diagram?

For example, a user place a node wherever he wants on the diagram from a palette, and then thanks to buttons placed on the node itself, the user creates children of this node that are well positioned under the node because of the layout. And then he can create sub children, etc…

However, I would like the user to be able to create other trees from other nodes wherever he wants on the digram from the palette.

I see there are group layouts but that demands to create a group for each new node put on the digram.

Set TreeLayout | GoJS API to go.TreeLayout.ArrangementFixedRoots.

Thank you Walter.

When set the layout like this :

diagram.layout = $(go.TreeLayout, {
treeStyle: go.TreeLayout.StyleLastParents,
alignment: go.TreeLayout.AlignmentCenterChildren,
arrangement: go.TreeLayout.ArrangementFixedRoots,
angle: 270,
layerSpacing: 10,
nodeSpacing: 100,
breadthLimit: 100,
});

and isLayoutPositioned: false to the nodeTemplate of the diagram (coming from the palette), the child of the nodes are all put in one place at the center of the diagram instead of neatly below each node.

the function to add a child is :

const addChild = function () {
let diagram = diagramRef.current.getDiagram();
var selnode = diagram.selection.first();
if (!(selnode instanceof go.Node)) return;
diagram.commit(function (d) {
var newnode = { key: “N” };
d.model.addNodeData(newnode); // this makes sure the key is unique
var newlink = { from: selnode.data.key, to: newnode.key };
d.model.addLinkData(newlink);
}, “add node and link”);
};

If the layout isn’t going to move any root nodes, you had better be sure before the layout that they have the locations that you want.

Your code to add a node and link look OK. But if the TreeLayout.angle is 270, that means the trees grow upwards, not downwards.

Wait, are you saying that the new nodes are small black squares?

The root nodes are the white rectangle (I placed three from the palette) and I don’t want the layout to move them (the user is sure to put them at this location).

For each of these nodes, I called addChild so the blacksquares are the children of the root nodes and the layout placed them all at the same place.

I find that it works as I think you are expecting. Here’s a complete sample that uses double-click in the background to create a new (root) node:

<!DOCTYPE html>
<html>
<head>
<!-- Copyright 1998-2019 by Northwoods Software Corporation. -->
<meta charset="UTF-8">
<script src="go.js"></script>
<script>
  function init() {
    var $ = go.GraphObject.make;

    myDiagram =
      $(go.Diagram, "myDiagramDiv",
          {
            "undoManager.isEnabled": true,
            layout: $(go.TreeLayout,
                      { arrangement: go.TreeLayout.ArrangementFixedRoots }),
            "clickCreatingTool.archetypeNodeData": { text: "new node", color: "yellow" }
          });

    myDiagram.nodeTemplate =
      $(go.Node, "Spot",
        { locationSpot: go.Spot.Center, locationObjectName: "BODY", selectionObjectName: "BODY" },
        $(go.Panel, "Auto",
          { name: "BODY" },
          $(go.Shape,
            { fill: "white", portId: "" },
            new go.Binding("fill", "color")),
          $(go.TextBlock,
            { margin: 8 },
            new go.Binding("text"))
        ),
        $("Button",
          $(go.Shape, "PlusLine", { width: 8, height: 8 }),
          {
            alignment: go.Spot.BottomRight,
            click: function(e, button) {
              var parentnode = button.part;
              e.diagram.model.commit(function(m) {
                var childdata = { text: "new child", color: "orange" };
                m.addNodeData(childdata);
                m.addLinkData({ from: parentnode.key, to: childdata.key })
              })
            }
          }
        )
      );

    myDiagram.model = new go.GraphLinksModel(
    [
      { key: 1, text: "Alpha", color: "lightblue" },
      { key: 2, text: "Beta", color: "orange" },
      { key: 3, text: "Gamma", color: "lightgreen" },
      { key: 4, text: "Delta", color: "pink" }
    ],
    [
      { from: 1, to: 2 },
      { from: 1, to: 3 },
      { from: 3, to: 4 }
    ]);
  }
</script>
</head>
<body onload="init()">
  <div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:600px"></div>
</body>
</html>

Thank you very much for your answer. That made me realize that an option messed everything on my diagram : "isTreePathToChildren": false

However, it seems that grouping one part of the layout causes problems in the links.

The TreeLayout properties you quoted above specify the TreeLayout.treeStyle to be “StyleLastParents”, yet you don’t specify any “alternate…” properties on the TreeLayout to control what happens for those parent vertexes.

Also, what is your Group.layout? If you want it to be treated as if the group weren’t there, set it to null. But if you want the default behavior where it is treated as a single node, I suggest you set Group.layout appropriately for your needs.

Edit: Finally I think I will use group layouts and if the user wants to make groups inside layout (tree) they will use a free shape that is not a “group” but will make it so the background is another color.

I removed treeStyle and I put the layout of the group to null. Yet, if I add a child next to the group, the links get messy.

Before adding:


after adding:

Precisely which version of go.js are you using?

Have you set Link.routing to go.Link.AvoidsNodes? For a tree-structure that has been laid out by TreeLayout, that should not be necessary – just setting routing: go.Link.Orthogonal will produce what I think you want.