Another routing issue

Hi Walter, I found another link routing issue. In the following diagram

I want to add a box between Box9 and Box15 (on the right-hand side of Box9).

What I got is following

Notice that Box15 is at a wrong location. Or I can say the link from Box7 to Box13 is routed incorrectly because the link is overlapped with Box 15. Same routing issue happens with the link from Box10 to Box13 and the link from Box11 to Box13.

It is another routing issue only with a node being dynamically added. When the diagram is loaded with the updated nodes and links, the diagram layout and link routings are correct. However, the problematic links are not associated with the end node this time :(

I am pasting the HTML + JS code below. Please only click the Add Box once, which will add Box16 on the right-hand side of Box9. Thank you so much!

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div
      id="myDiagramDiv"
      style="border: solid 1px black; width: 100%; height: 900px"
    ></div>
    <div class="row">
        <button id="add">Add Box</button>
    </div>
    <script src="../../site/release/go-debug.js"></script>
    <script>
        let myDiagram;
    function init() {
        const $ = go.GraphObject.make;
        myDiagram = $(go.Diagram, "myDiagramDiv", {
            layout: $(go.LayeredDigraphLayout, {
                layeringOption: go.LayeredDigraphLayout.LayerLongestPathSource,
                packOption: go.LayeredDigraphLayout.PackStraighten,
                aggressiveOption: go.LayeredDigraphLayout.AggressiveNone,
                layerSpacing: 50,
                linkSpacing: 20,
                alignOption: go.LayeredDigraphLayout.AlignAll,
            }),
        });

        myDiagram.nodeTemplateMap.add("global", $(
            go.Node,
            "Spot",
            $(go.Shape, "Circle", {
            fill: "transparent",
            stroke: '#01778e',
            width: 50,
            height: 50,
            portId: "",
            fromLinkable: true,
            toLinkable: true,
            cursor: "pointer",
            }),
            $(
            go.TextBlock,
            new go.Binding("text", "key"),
            {
                verticalAlignment: go.Spot.Center,
                textAlign: "center",
                stroke: '#1d2024',
            },
            ),
            $(go.Shape, "Rectangle", {
                fill: null,
                stroke: null,
                desiredSize: new go.Size(0, 0),
                alignment: new go.Spot(0, 0.5, 0, 0),
                portId: "Left",
                fromSpot: go.Spot.Left,
                toSpot: go.Spot.Left,
            }),
            $(go.Shape, "Rectangle", {
                fill: null,
                stroke: null,
                desiredSize: new go.Size(0, 0),
                alignment: new go.Spot(1, 0.5, 0, 0),
                portId: "Right",
                fromSpot: go.Spot.Right,
                toSpot: go.Spot.Right,
            }),
        ));

        myDiagram.nodeTemplateMap.add("", $(
            go.Node,
            "Spot",
            $(go.Shape, "Rectangle", {
                fill: "transparent",
                stroke: "transparent",
                width: 124,
                height: 152,
                portId: "",
                fromLinkable: true,
                toLinkable: true,
                cursor: "pointer",
            }),
            $(
            go.Panel,
            "Position",
            $(go.Shape, "RoundedRectangle", {
                fill: "transparent",
                width: 64,
                height: 64,
                position: new go.Point(0, 12),
            }),
            $(
                go.TextBlock,
                new go.Binding("text", "key"),
                {
                width: 64,
                position: new go.Point(0, 84),
                verticalAlignment: go.Spot.Center,
                textAlign: "center",
                },
            ),
            ),
            $(go.Shape, "Rectangle", {
                fill: null,
                stroke: null,
                desiredSize: new go.Size(0, 0),
                alignment: new go.Spot(0, 0.5, 30, 0),
                portId: "Left",
                fromSpot: go.Spot.Left,
                toSpot: go.Spot.Left,
            }),
            $(go.Shape, "Rectangle", {
                fill: null,
                stroke: null,
                desiredSize: new go.Size(0, 0),
                alignment: new go.Spot(1, 0.5, -30, 0),
                portId: "Right",
                fromSpot: go.Spot.Right,
                toSpot: go.Spot.Right,
            }),
        ));

        myDiagram.nodeTemplateMap.add("group-end", $(go.Node, 'Spot',
            $(go.Shape, "Circle", {
                width: 0,
                height: 0,
                alignment: go.Spot.Center,
                fill: null,
                stroke: null,
            }),
            $(go.Shape, "Rectangle", {
                fill: null,
                stroke: null,
                desiredSize: new go.Size(0, 0),
                alignment: new go.Spot(0, 0.5),
                portId: "Left",
                fromSpot: go.Spot.Left,
                toSpot: go.Spot.Left,
            }),
            $(go.Shape, "Rectangle", {
                fill: null,
                stroke: null,
                desiredSize: new go.Size(0, 0),
                alignment: new go.Spot(1, 0.5),
                portId: "Right",
                fromSpot: go.Spot.Right,
                toSpot: go.Spot.Right,
            }),
        ));

        myDiagram.linkTemplate = $(
            go.Link,
            go.Link.Orthogonal,
            {
                relinkableFrom: true,
                relinkableTo: true,
                selectable: true,
                reshapable: true,
                corner: 10,
                toShortLength: 8,
                fromEndSegmentLength: 40,
                toEndSegmentLength: 40,
                routing: go.Link.AvoidsNodes,
            },
            $(go.Shape, { isPanelMain: true, strokeWidth: 1 }),
            $(go.Shape, {
                toArrow: "Standard",
            }),
        );

        myDiagram.groupTemplate = $(
            go.Group,
            "Spot",
            {
            layout: $(go.LayeredDigraphLayout, {
                layeringOption: go.LayeredDigraphLayout.LayerLongestPathSource,
                packOption: go.LayeredDigraphLayout.PackStraighten,
                aggressiveOption: go.LayeredDigraphLayout.AggressiveNone,  
                layerSpacing: 50,
                linkSpacing: 20,
                alignOption: go.LayeredDigraphLayout.AlignAll,
                isRouting: false
            }),
            },
            $(go.Panel, "Horizontal",
                $(go.Shape, "Rectangle", {
                    width: 30,
                    fill: "transparent",
                    strokeWidth: 0,
                    stretch: go.GraphObject.Fill
                }),
                $(go.Panel, "Auto",
                    $(go.Shape, "Rectangle", {
                    fill: "transparent",
                    strokeWidth: 0,
                    stretch: go.GraphObject.Fill
                    }),
                    $(go.Panel, "Auto", 
                    $(
                        go.Shape,
                        "RoundedRectangle", // surrounds everything
                        {
                            parameter1: 10,
                            fill: "white",
                            stroke: '#999999',
                            minSize: new go.Size(240, 220),
                            spot1: go.Spot.TopLeft,
                            spot2:go.Spot.BottomRight
                        }
                    ),
                    $(
                        go.Panel,
                        "Vertical", // position header above the subgraph
                        $(go.Panel, "Auto", {
                        height: 28,
                        alignment: go.Spot.Left,
                        padding: new go.Margin(8, 12, 0, 12),
                        }, $(go.TextBlock, // stage title near top, next to button
                        new go.Binding("text", "key")
                        )),
                        $(
                        go.Placeholder, // represents area for all member parts
                        {
                            padding: new go.Margin(4, 0, 4, 0),
                            background: "transparent",
                            minSize: new go.Size(240, 160),
                        }
                        ),
                        $(go.Panel, "Auto", {
                        height: 28,
                        stretch: go.GraphObject.Fill
                        })
                    )
                    )
                ),
                $(go.Shape, "Rectangle", {
                    width: 30,
                    fill: "transparent",
                    strokeWidth: 0,
                    stretch: go.GraphObject.Fill
                })
            ),
            $(go.Shape, "Rectangle", {
                fill: null,
                stroke: null,
                desiredSize: new go.Size(0, 0),
                alignment: new go.Spot(0, 0.5, 30, 0),
                portId: "Left",
                fromSpot: go.Spot.Left,
                toSpot: go.Spot.Left,
            }),
            $(go.Shape, "Rectangle", {
                fill: null,
                stroke: null,
                desiredSize: new go.Size(0, 0),
                alignment: new go.Spot(1, 0.5, -30, 0),
                portId: "Right",
                fromSpot: go.Spot.Right,
                toSpot: go.Spot.Right,
            }
        ));

        const nodeDataArray = [
            {
                key: "Start",
                category: "global",
            },
            {
                key: "End",
                category: "global",
            },
            {
                key: "Group1",
                isGroup: true,
            },
            {
                key: "Group1-start",
                group: "Group1",
                category: "group-end"
            },
            {
                key: "Group1-end",
                group: "Group1",
                category: "group-end"
            },
            {
                key: "Box1",
                group: "Group1",                
            },
            {
                key: "Box2",
                group: "Group1",                
            },
            {
                key: "Box3",
                group: "Group1",                
            },
            {
                key: "Box4",
                group: "Group1",                
            },
            {
                key: "Box5",
                group: "Group1",                
            },
            {
                key: "Box6",
                group: "Group1",                
            },
            {
                key: "Box7",
                group: "Group1",                
            },
            {
                key: "Box8",
                group: "Group1",                
            },
            {
                key: "Box9",
                group: "Group1",                
            },
            {
                key: "Box10",
                group: "Group1",                
            },
            {
                key: "Box11",
                group: "Group1",                
            },
            {
                key: "Box12",
                group: "Group1",                
            },
            {
                key: "Box13",
                group: "Group1",                
            },
            {
                key: "Box14",
                group: "Group1",                
            },
            {
                key: "Box15",
                group: "Group1",                
            },
        ];

        const linkDataArray = [
            {
                from: "Start",
                to: "Group1",
                fromPort: "Right",
                toPort: "Left",
            },
            {
                from: "Group1",
                to: "End",
                fromPort: "Right",
                toPort: "Left",
            },
            {
                from: "Group1-start",
                to: "Box2",
                fromPort: "Right",
                toPort: "Left",
            },
            {
                from: "Box2",
                to: "Box1",
                fromPort: "Right",
                toPort: "Left",
            },
            {
                from: "Box2",
                to: "Box3",
                fromPort: "Right",
                toPort: "Left",
            },
            {
                from: "Box2",
                to: "Box6",
                fromPort: "Right",
                toPort: "Left",
            },
            {
                from: "Box2",
                to: "Box8",
                fromPort: "Right",
                toPort: "Left",
            },
            {
                from: "Box1",
                to: "Box4",
                fromPort: "Right",
                toPort: "Left",
            },
            {
                from: "Box3",
                to: "Box5",
                fromPort: "Right",
                toPort: "Left",
            },
            {
                from: "Box3",
                to: "Box7",
                fromPort: "Right",
                toPort: "Left",
            },
            {
                from: "Box6",
                to: "Box9",
                fromPort: "Right",
                toPort: "Left",
            },
            {
                from: "Box6",
                to: "Box10",
                fromPort: "Right",
                toPort: "Left",
            },
            {
                from: "Box8",
                to: "Box11",
                fromPort: "Right",
                toPort: "Left",
            },
            {
                from: "Box5",
                to: "Box4",
                fromPort: "Right",
                toPort: "Left",
            },
            {
                from: "Box4",
                to: "Box14",
                fromPort: "Right",
                toPort: "Left",
            },
            {
                from: "Box14",
                to: "Box13",
                fromPort: "Right",
                toPort: "Left",
            },
            {
                from: "Box7",
                to: "Box13",
                fromPort: "Right",
                toPort: "Left",
            },
            {
                from: "Box9",
                to: "Box15",
                fromPort: "Right",
                toPort: "Left",
            },
            {
                from: "Box15",
                to: "Box13",
                fromPort: "Right",
                toPort: "Left",
            },
            {
                from: "Box10",
                to: "Box13",
                fromPort: "Right",
                toPort: "Left",
            },      
            {
                from: "Box11",
                to: "Box13",
                fromPort: "Right",
                toPort: "Left",
            },
            {
                from: "Box13",
                to: "Box12",
                fromPort: "Right",
                toPort: "Left",
            },
            {
                from: "Box12",
                to: "Group1-end",
                fromPort: "Right",
                toPort: "Left",
            }
        ];

        const model = new go.GraphLinksModel();
        model.nodeDataArray = nodeDataArray;
        model.linkDataArray = linkDataArray;
        model.linkFromPortIdProperty = "fromPort";
        model.linkToPortIdProperty = "toPort";
        model.nodeGroupKey = "group";
        myDiagram.model = model;
    }

    window.addEventListener("DOMContentLoaded", init);  
    document.getElementById('add').addEventListener('click', e => {
        const node = myDiagram.findNodeForKey('Box9');
        const groupKey = node.data.group;

        const linkIt = node.findLinksOutOf();
        const linksOutOf = new go.List();
        while (linkIt.next()) {
            linksOutOf.add(linkIt.value);
        }

        const existingKey = node.data.key;
        const newKey = 'Box16';
        myDiagram.model.addNodeData({ key: newKey, group: groupKey });
        myDiagram.model.addLinkData({
            from: existingKey,
            fromPort: "Right",
            to: newKey,
            toPort: "Left",
        });
        linksOutOf.each(link => {
            const toNodeKey = link.toNode.data.key;
            myDiagram.model.removeLinkData(link.data);
            myDiagram.model.addLinkData({
            from: newKey,
            fromPort: "Right",
            to: toNodeKey,
            toPort: "Left",
            hidden: link.data.hidden,
            });
        });
    });   
    </script>
  </body>
</html>

You aren’t using the custom LayeredDigraphLayout that I gave you. Try this variation:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div
      id="myDiagramDiv"
      style="border: solid 1px black; width: 100%; height: 700px"
    ></div>
    <div class="row">
        <button id="add">Add Box</button>
        <button onclick="load(0)">Reload 0</button>
        <button onclick="load(1)">Reload 1</button>
    </div>
    <script src="https://unpkg.com/gojs"></script>
    <script>

// Route all orthogonal links coming into a "group-end" category node to
// turn at the same x point. This only works for direction: 0.
class ParallelLDLayout extends go.LayeredDigraphLayout {
  constructor() {
    super();
    this.alignOption = go.LayeredDigraphLayout.AlignAll;
    this.layeringOption = go.LayeredDigraphLayout.LayerLongestPathSource;
    this.layerSpacing = 50;
    this.linkSpacing = 20;
  }

  commitLinks() {
    super.commitLinks();
    this.network.vertexes.each(v => {
      if (v.node /*&& v.node.category === "group-end"*/) {
        // assume this.direction === 0
        let x = v.node.port.getDocumentBounds().x - 30;
        v.sourceEdges.each(e => {
          const link = e.link;
          if (link && link.isOrthogonal) {
            const num = link.pointsCount;
            if (num >= 6) {
              const pts = link.points.copy();
              const p3 = pts.elt(num-3);
              pts.setElt(3, new go.Point(x, p3.y));
              const p2 = pts.elt(num-4);
              pts.setElt(2, new go.Point(x, p2.y));
              link.points = pts;
            }
          }
        });
      }
    });
  }
}


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

    myDiagram = $(go.Diagram, "myDiagramDiv",
      {
        layout: new ParallelLDLayout()
      });

    myDiagram.nodeTemplateMap.add("global", $(go.Node, "Spot",
      $(go.Shape, "Circle", {
        fill: "transparent",
        stroke: '#01778e',
        width: 50,
        height: 50,
        portId: "",
        fromLinkable: true,
        toLinkable: true,
        cursor: "pointer",
        }),
      $(go.TextBlock,
        new go.Binding("text", "key"),
        {
            verticalAlignment: go.Spot.Center,
            textAlign: "center",
            stroke: '#1d2024',
        }),
      $(go.Shape, "Rectangle", {
            fill: null,
            stroke: null,
            desiredSize: new go.Size(0, 0),
            alignment: new go.Spot(0, 0.5, 0, 0),
            portId: "Left",
        }),
      $(go.Shape, "Rectangle", {
            fill: null,
            stroke: null,
            desiredSize: new go.Size(0, 0),
            alignment: new go.Spot(1, 0.5, 0, 0),
            portId: "Right",
        }),
    ));

    myDiagram.nodeTemplate = $(go.Node, "Spot",
        $(go.Shape, "Rectangle", {
            fill: "transparent",
            stroke: "transparent",
            width: 124,
            height: 152,
            portId: "",
            fromLinkable: true,
            toLinkable: true,
            cursor: "pointer",
        }),
        $(go.Panel, "Position",
          $(go.Shape, "RoundedRectangle", {
              fill: "transparent",
              width: 64,
              height: 64,
              position: new go.Point(0, 12),
          }),
          $(go.TextBlock,
              new go.Binding("text", "key"),
              {
              width: 64,
              position: new go.Point(0, 84),
              verticalAlignment: go.Spot.Center,
              textAlign: "center",
              },
          ),
        ),
        $(go.Shape, "Rectangle", {
            fill: null,
            stroke: null,
            desiredSize: new go.Size(0, 0),
            alignment: new go.Spot(0, 0.5, 30, 0),
            portId: "Left",
        }),
        $(go.Shape, "Rectangle", {
            fill: null,
            stroke: null,
            desiredSize: new go.Size(0, 0),
            alignment: new go.Spot(1, 0.5, -30, 0),
            portId: "Right",
        }),
    );

    myDiagram.nodeTemplateMap.add("group-start",
      $(go.Node));

    myDiagram.nodeTemplateMap.add("group-end",
      $(go.Node));

    myDiagram.linkTemplate = $(go.Link,
        //go.Link.Orthogonal,
        {
            relinkableFrom: true,
            relinkableTo: true,
            selectable: true,
            reshapable: true,
            corner: 10,
            toShortLength: 8,
            fromEndSegmentLength: 40,
            toEndSegmentLength: 40,
            routing: go.Link.Orthogonal, //go.Link.AvoidsNodes,
        },
        $(go.Shape, { strokeWidth: 1 }),
        $(go.Shape, { toArrow: "Standard" }),
    );

    myDiagram.groupTemplate = $(go.Group, "Spot",
        {
          layout: new ParallelLDLayout()
        },
        $(go.Panel, "Horizontal",
            $(go.Shape, "Rectangle", {
                width: 30,
                fill: "transparent",
                strokeWidth: 0,
                stretch: go.GraphObject.Fill
            }),
            $(go.Panel, "Auto",
              $(go.Shape, "Rectangle", {
                fill: "transparent",
                strokeWidth: 0,
                stretch: go.GraphObject.Fill
              }),
              $(go.Panel, "Auto", 
                $(go.Shape, "RoundedRectangle", // surrounds everything
                    {
                        parameter1: 10,
                        fill: "white",
                        stroke: '#999999',
                        minSize: new go.Size(240, 220),
                        spot1: go.Spot.TopLeft,
                        spot2:go.Spot.BottomRight
                    }
                ),
                $(go.Panel, "Vertical", // position header above the subgraph
                  $(go.Panel, "Auto", {
                      height: 28,
                      alignment: go.Spot.Left,
                      padding: new go.Margin(8, 12, 0, 12),
                    },
                    $(go.TextBlock, // stage title near top, next to button
                      new go.Binding("text", "key")
                    )
                  ),
                  $(go.Placeholder, // represents area for all member parts
                    {
                        padding: new go.Margin(4, 0, 4, 0),
                        background: "transparent",
                        minSize: new go.Size(240, 160),
                    }),
                  $(go.Panel, "Auto", {
                    height: 28,
                    stretch: go.GraphObject.Fill
                    })
                )
              )
            ),
            $(go.Shape, "Rectangle", {
                width: 30,
                fill: "transparent",
                strokeWidth: 0,
                stretch: go.GraphObject.Fill
            })
        ),
        $(go.Shape, "Rectangle", {
            fill: null,
            stroke: null,
            desiredSize: new go.Size(0, 0),
            alignment: new go.Spot(0, 0.5, 30, 0),
            portId: "Left",
        }),
        $(go.Shape, "Rectangle", {
            fill: null,
            stroke: null,
            desiredSize: new go.Size(0, 0),
            alignment: new go.Spot(1, 0.5, -30, 0),
            portId: "Right",
        }
    ));

    load(0);
}

function load(choice) {
  let nda = [];
  let lda = [];
  if (choice === 0) {    
    nda = [
      {
          key: "Start",
          category: "global",
      },
      {
          key: "End",
          category: "global",
      },
      {
          key: "Group1",
          isGroup: true,
      },
      {
          key: "Group1-start",
          group: "Group1",
          category: "group-start"
      },
      {
          key: "Group1-end",
          group: "Group1",
          category: "group-end"
      },
      {
          key: "Box1",
          group: "Group1",                
      },
      {
          key: "Box2",
          group: "Group1",                
      },
      {
          key: "Box3",
          group: "Group1",                
      },
      {
          key: "Box4",
          group: "Group1",                
      }
    ];
    lda = [
      {
          from: "Start",
          to: "Group1",
          fromPort: "Right",
          toPort: "Left",
      },
      {
          from: "Group1",
          to: "End",
          fromPort: "Right",
          toPort: "Left",
      },
      {
          from: "Group1-start",
          to: "Box1",
          fromPort: "Right",
          toPort: "Left",
      },
      {
          from: "Box1",
          to: "Box2",
          fromPort: "Right",
          toPort: "Left",
      },
      {
          from: "Box2",
          to: "Box3",
          fromPort: "Right",
          toPort: "Left",
      },
      {
          from: "Box2",
          to: "Box4",
          fromPort: "Right",
          toPort: "Left",
      },
      {
          from: "Box3",
          to: "Group1-end",
          fromPort: "Right",
          toPort: "Left",
      },
      {
          from: "Box4",
          to: "Group1-end",
          fromPort: "Right",
          toPort: "Left",
      }
    ];
  } else if (choice === 1) {
    nda = [
      {
          key: "Start",
          category: "global",
      },
      {
          key: "End",
          category: "global",
      },
      {
          key: "Group1",
          isGroup: true,
      },
      {
          key: "Group1-start",
          group: "Group1",
          category: "group-start"
      },
      {
          key: "Group1-end",
          group: "Group1",
          category: "group-end"
      },
      {
          key: "Box1",
          group: "Group1",                
      },
      {
          key: "Box2",
          group: "Group1",                
      },
      {
          key: "Box3",
          group: "Group1",                
      },
      {
          key: "Box4",
          group: "Group1",                
      },
      {
          key: "Box5",
          group: "Group1",                
      },
      {
          key: "Box6",
          group: "Group1",                
      },
      {
          key: "Box7",
          group: "Group1",                
      }
    ];
    lda = [
      {
          from: "Start",
          to: "Group1",
          fromPort: "Right",
          toPort: "Left",
      },
      {
          from: "Group1",
          to: "End",
          fromPort: "Right",
          toPort: "Left",
      },
      {
          from: "Group1-start",
          to: "Box1",
          fromPort: "Right",
          toPort: "Left",
      },
      {
          from: "Box1",
          to: "Box2",
          fromPort: "Right",
          toPort: "Left",
      },
      {
          from: "Box1",
          to: "Box7",
          fromPort: "Right",
          toPort: "Left",
      },
      {
          from: "Box2",
          to: "Box3",
          fromPort: "Right",
          toPort: "Left",
      },
      {
          from: "Box2",
          to: "Box6",
          fromPort: "Right",
          toPort: "Left",
      },
      {
          from: "Box3",
          to: "Box4",
          fromPort: "Right",
          toPort: "Left",
      },
      {
          from: "Box3",
          to: "Box5",
          fromPort: "Right",
          toPort: "Left",
      },
      {
          from: "Box4",
          to: "Group1-end",
          fromPort: "Right",
          toPort: "Left",
      },
      {
          from: "Box5",
          to: "Group1-end",
          fromPort: "Right",
          toPort: "Left",
      },
      {
          from: "Box6",
          to: "Group1-end",
          fromPort: "Right",
          toPort: "Left",
      },
      {
          from: "Box7",
          to: "Group1-end",
          fromPort: "Right",
          toPort: "Left",
      }
    ];
  }

    const model = new go.GraphLinksModel();
    model.nodeDataArray = nda;
    model.linkDataArray = lda;
    model.linkFromPortIdProperty = "fromPort";
    model.linkToPortIdProperty = "toPort";
    model.nodeGroupKey = "group";
    myDiagram.model = model;
}

window.addEventListener("DOMContentLoaded", init);  

document.getElementById('add').addEventListener('click', e => {
    const groupKey = 'Group1'
    const endKey = `${groupKey}-end`;
    const existingKey = 'Box1';
    const newdata = { group: groupKey };
    myDiagram.model.addNodeData(newdata);
    const newKey = newdata.key;
    myDiagram.model.addLinkData({
        from: existingKey,
        fromPort: "Right",
        to: newKey,
        toPort: "Left",
    });
    myDiagram.model.addLinkData({
        from: newKey,
        fromPort: "Right",
        to: endKey,
        toPort: "Left",
    });        
});   
    </script>
  </body>
</html>

Note how the layout is being declared. Note also that I didn’t bother setting the fromSpot or toSpot on any port – it’s set by the LayeredDigraphLayout.

Interesting… we adjust the routing for all the links. And it works :)

Thank you, Walter!