How can I fix my diagram layout problem?

I’m creating a diagram which is created incrementally adding nodes and links calling my backend api and I’m trying to figure out which layout fits best for my purpose.
I tried two types of layout: the BandedTreeLayout (same as the one found in samples) and the LayeredDigraphLayout.

Case BandedTreeLayout
This is my layout with its options:

      layout: $(BandedTreeLayout, {
        angle: 0,
        arrangement: go.TreeLayout.ArrangementHorizontal,

        treeStyle: go.TreeLayout.StyleLayered,
        alignment: go.TreeLayout.AlignmentCenterChildren,
        nodeSpacing: 20,
        nodeIndent: 0,
        nodeIndentPastParent: 0,
        layerSpacing: 150,
        layerSpacingParentOverlap: 0,
        compaction: go.TreeLayout.CompactionBlock,
        breadthLimit: 0,
        rowSpacing: 20,
        rowIndent: 10,
        setsPortSpot: false,
        setsChildPortSpot: false,
      })

The result is good as you can see in the picture below:

and adding new nodes the result is always good until I add some nodes that are parent and in that case the result isn’t good as you can see in the picture below:

Using this layout is it possible to add parents not at the top of all the diagram, but in a more well-ordered way?

Case LayeredDigraphLayout
This is my layout with its options:

  > layout: $(go.LayeredDigraphLayout, {
    direction: 0,
    layerSpacing: 50,
    columnSpacing: 50,
    cycleRemoveOption: go.LayeredDigraphLayout.CycleGreedy, //.CycleDepthFirst,
    layeringOption: go.LayeredDigraphLayout.LayerLongestPathSource,
    initializeOption: go.LayeredDigraphLayout.InitDepthFirstOut,
    aggressiveOption: go.LayeredDigraphLayout.AggressiveMore,
    packOption: go.LayeredDigraphLayout.PackAll,

    isRouting: true,

    setsPortSpots: false,
  }),

The result is good except for the links that behave in a very strange way
graph1

and expanding the parents, the new nodes are arranged in a good place, but as I said the links are a mess

This is my link template:

$(
    go.Link,
    {
      routing: go.Link.AvoidsNodes,
      layerName: "Background",
      zOrder: 2,
      corner: 5,
      curve: go.Link.JumpGap,
    },
    $(go.Shape, { strokeWidth: 1.5, stroke: "#A9A9A9" }),
    $(go.Shape, { toArrow: "standard", stroke: null, fill: "#A9A9A9" }),
    $(
      go.TextBlock,
      {
        textAlign: "center",
        font: "9pt helvetica, arial, sans-serif",
        margin: 4,
        segmentIndex: 3,
        segmentFraction: 0.6,
        segmentOffset: new go.Point(0, -5),
      },
      new go.Binding("text", "LinkName"),
      new go.Binding("text", "LinkLabel")
    )
  )

The only thing in the entity template that I think is important to mention is the fromSpot and toSpot

fromSpot: go.Spot.AllSides, 
toSpot: go.Spot.LeftSide,

What can I change in order to obtain a good solution?

Try setting LayeredDigraphLayout.setsPortSpots to false.

Is already set to false, is the last option in the layout in the code of my first post.

Sorry, I missed that. I cannot explain why you are getting that routing behavior. If the fromSpot really is go.Spot.AllSides, the links to nearby nodes on the right should be on the right side. Links to nodes that are significantly above or below (Y coordinate) should have the links coming out from the top or the bottom of the node.

Might there be anything else in your graph that would be causing these odd results? Later today I can try reproducing this configuration.

Thanks for your reply Walter, I’m thinking about other possibilities.

You can see here the diagram options

myDiagram = $(go.Diagram, "myDiagramDiv", {
  initialContentAlignment: go.Spot.Center,
  contentAlignment: go.Spot.Center,
  initialAutoScale: go.Diagram.UniformToFill,

  layout: $(go.LayeredDigraphLayout, {
    direction: 0,
    layerSpacing: 50,
    columnSpacing: 30,
    cycleRemoveOption: go.LayeredDigraphLayout.CycleGreedy, 
    layeringOption: go.LayeredDigraphLayout.LayerLongestPathSource,
    initializeOption: go.LayeredDigraphLayout.InitDepthFirstOut,
    aggressiveOption: go.LayeredDigraphLayout.AggressiveMore,
    packOption: go.LayeredDigraphLayout.PackAll,

    isRouting: true,

    setsPortSpots: false,
  }),

  "undoManager.isEnabled": true,
  "linkingTool.isEnabled": false,
  "draggingTool.dragsLink": false,
})

Can the container style be responsible of that?

<div
id="myDiagramDiv"
style={{
  width: "100%",
  position: "absolute",
  top: 0,
  bottom: 0,
}} />

OK, here’s what I just tried:

    myDiagram =
      $(go.Diagram, "myDiagramDiv",
          { // your Diagram.layout:
            layout: $(go.LayeredDigraphLayout,
              {
                direction: 0,
                layerSpacing: 50,
                columnSpacing: 30,
                cycleRemoveOption: go.LayeredDigraphLayout.CycleGreedy,
                layeringOption: go.LayeredDigraphLayout.LayerLongestPathSource,
                initializeOption: go.LayeredDigraphLayout.InitDepthFirstOut,
                aggressiveOption: go.LayeredDigraphLayout.AggressiveMore,
                packOption: go.LayeredDigraphLayout.PackAll,
                isRouting: true,
                setsPortSpots: false
              }),
          });

    myDiagram.nodeTemplate =
      $(go.Node, "Auto",
        { width: 150, height: 40 },
        $(go.Shape,
          {
            fill: "white", portId: "", cursor: "pointer",
            fromSpot: go.Spot.AllSides, fromLinkable: true,
            toSpot: go.Spot.Left, toLinkable: true
          },
          new go.Binding("fill", "color")),
        $(go.TextBlock,
          new go.Binding("text"))
      );

    myDiagram.linkTemplate =
      $(go.Link,
        $(go.Shape),
        $(go.Shape, { toArrow: "OpenTriangle" })
      );

    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" },
      { key: 5, text: "Epsilon", color: "lightyellow" },
      { key: 6, text: "Zeta", color: "lavender" },
      { key: 7, text: "Eta", color: "beige" },
      { key: 8, text: "Theta", color: "lightgray" },
    ],
    [
      { from: 1, to: 2 },
      { from: 1, to: 3 },
      { from: 1, to: 4 },
      { from: 1, to: 5 },
      { from: 1, to: 6 },
      { from: 1, to: 7 },
      { from: 1, to: 8 },
    ]);

This results in this screenshot:

Hi Walter, thanks for your reply.

With your settings this is the result and it is so weird
graph3

by the way I would like to maintain the orthogonal setting.

I was in a hurry, so I forgot to set Link.routing to Orthogonal and add a label to the link. So:

    myDiagram.linkTemplate =
      $(go.Link,
        { routing: go.Link.Orthogonal, corner: 10 },
        $(go.Shape),
        $(go.Shape, { toArrow: "OpenTriangle" }),
        $(go.TextBlock, "label",
          { segmentIndex: -1, segmentOffset: new go.Point(NaN, NaN) })
      );

then produces:

You have basically the complete source code for the diagram that I’m including in this forum post, so I’m curious what’s different in your case. Clearly the contents of the nodes are different. I suppose you could experiment with deleting all of the node contents to see if you still get the same results.

Hi Walter,
I figure out that the problem resides in the entity template because I didn’t fix a width in the Node, but I used the defaultStretch option in the panel inside as you can see in my code

$(
    go.Node,
    "Auto",
    {
      zOrder: 3,
      portId: "",
      fromSpot: go.Spot.AllSides,
      fromLinkable: true,
      toSpot: go.Spot.Left,
      toLinkable: true,
    },
    $(go.Shape, "Rectangle", {
      fill: "white",
      stroke: "transparent",
    }),
    $(
      go.Panel,
      "Vertical",
      {
        defaultStretch: go.GraphObject.Horizontal,
      },

      // upper bar
      $(
        go.Panel,
        "Auto",
        $(
          go.Shape,
          "RoundedTopRectangle",
          {
            height: 20,
          },
          new go.Binding("fill", "ColorHex"),
          new go.Binding("stroke", "ColorHex")
        ),
        $(
          go.Panel,
          "Table",
          {
            padding: 0.5,
            defaultStretch: go.GraphObject.Horizontal,
          },
          $(go.RowColumnDefinition, { column: 0, width: 14 }),
          $(
            go.Shape,
            {
              column: 0,
              width: 10,
              height: 10,
              margin: 2,
              strokeWidth: 0,
              fill: "#FFFFFF",
            },
            new go.Binding("geometry", "SvgIcon", icon => {
              const SvgIcon = go.Geometry.parse(icon, true)
              return SvgIcon
            })
          ),
          $(
            go.TextBlock,
            {
              column: 1,
              margin: 2,
              alignment: go.Spot.Center,
              stroke: "white",
              font: "bold 12px sans-serif",
            },
            new go.Binding("text", "EntityTypeName")
          )
        )
      ),

      // bottom bar
      $(
        go.Panel,
        "Auto",
        $(
          go.Shape,
          "RoundedBottomRectangle",
          {
            fill: "white",
            height: 20,
          },
          new go.Binding("stroke", "ColorHex")
        ),

        $(
          go.Panel,
          "Table",
          {
            defaultStretch: go.GraphObject.Horizontal,
          },
          $(
            go.Panel,
            "TableRow",
            // entity text
            $(
              go.TextBlock,
              {
                row: 0,
                column: 0,
                margin: 2,
                font: "bold 12px sans-serif",
                alignment: go.Spot.Center,
              },
              new go.Binding("stroke", "ColorHex"),
              new go.Binding("text", "EntityName")
            )
          )
        )
      )
    )

Is it a must have condition setting a fixed width or is it possible having nodes of different width created dynamically? Do you have a solution for that?

Thanks

That’s pretty wild. If you try fromSpot: go.Spot.NotLeftSide, do you get better results?

Yes I got better results, but I need that the links follow a direction and the direction I need is to the right, then in my case I have to set toSpot: go.Spot.LftSide is it possible to avoid that strange behavior?

Thanks

I don’t understand what you want. Could you show in a small screenshot what routes you are getting and sketch what you want instead?

Sure look at the pictures below:

I would like to have something like this
graph4

but I get this result
graph1

The cause as I wrote two post ago, resides in the dimension of node template that isn’t fixed because my nodes are dynamically created and I don’t know the dimension!

Wait – are you still getting that bad routing even when you have set fromSpot: go.Spot.NotLeftSide on your port?

Wait I set the toSpot instead of the fromSpot and using the NotLeftSide I got a good solution.
I guess that we can close the post! :-)
Many thanks as usual Walter