Is there a way to create Y Links?

Hi, I would like to create Y Links for the project I am currently working on.

I display two rectangular nodes: A and B.
Node A has two ports on the right side and their spot is “Right”, node B does not have any port, the Spot on its body is “Left”.
I have one link for each Node A’s port.

this is how they are currently displayed:

this is how I’d like them to be displayed:

Is there a way to create Y links like that? I am aware of Routers but I am not sure if it is the correct path to follow.
Thank you in advance.

P.S. I drew the scenario in excalidraw, I can’t disclose actual screenshots of the app because of NDA.

How have you defined your link template?

Did you get to the current situation (the first screenshot) by first connecting the nodes with two links and then moving one or both of the nodes? If so, perhaps the situation is due to having set the Link.adjusting property.

1 Like

Here’s what I just tried. The result:

The complete sample code:

<!DOCTYPE html>
<html>
<head>
  <title>Minimal GoJS Sample</title>
  <!-- Copyright 1998-2025 by Northwoods Software Corporation. -->
</head>
<body>
  <div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:400px"></div>

  <script src="https://cdn.jsdelivr.net/npm/gojs/release/go-debug.js"></script>
  <script id="code">
const myDiagram =
  new go.Diagram("myDiagramDiv", {
      "undoManager.isEnabled": true
    });

myDiagram.nodeTemplate =
  new go.Node("Spot", {
      locationSpot: go.Spot.Center,
      itemTemplate:
        new go.Panel()
          .bind("alignment", "spot", go.Spot.parse)
          .add(
            new go.Shape({ width: 16, height: 10, fill: "white" })
              .bind("portId", "id")
              .bind("fromSpot", "spot", s => {
                const spot = go.Spot.parse(s);
                return spot.x > 0.5 ? go.Spot.Right : go.Spot.Left;
              })
              .bind("toSpot", "spot", s => {
                const spot = go.Spot.parse(s);
                return spot.x > 0.5 ? go.Spot.Right : go.Spot.Left;
              })
          )
    })
    .bindTwoWay("location", "loc", go.Point.parse, go.Point.stringify)
    .bind("itemArray", "ports")
    .add(
      new go.Panel("Auto", { width: 150, height: 75, portId: "" })
        .add(
          new go.Shape({ fill: "white" })
            .bind("fill", "color"),
          new go.TextBlock({ editable: true })
            .bindTwoWay("text")
        )
  );

myDiagram.linkTemplate =
  new go.Link({
      routing: go.Link.Orthogonal, corner: 10,
      relinkableFrom: true, relinkableTo: true,
      reshapable: true, resegmentable: true
    })
    .add(
      new go.Shape()
    );

myDiagram.model = new go.GraphLinksModel(
  {
    linkFromPortIdProperty: "fid",
    linkToPortIdProperty: "tid",
    nodeDataArray:
    [
      {
        key: 1, text: "Node A", loc: "0 0",
        ports: [{ id: "a", spot: "1 0.15" }, { id: "b", spot: "1 0.85" }]
      },
      {
        key: 2, text: "Node B", loc: "250 0"
      }
    ],
    linkDataArray:
    [
      { from: 1, fid: "a", to: 2, tid: "" },
      { from: 1, fid: "b", to: 2, tid: "" },
    ]
  });
  </script>
</body>
</html>
1 Like