How to position an arrowhead at the end of the link when using toEndSegmentLength

Here’s my code for the linkTemplate:

myDiagram.linkTemplate =
      $$(go.Link,
        { routing: go.Link.AvoidsNodes, curve: go.Link.JumpGap, corner: 5, fromEndSegmentLength: 20, toEndSegmentLength: 20 },
        $$(go.Shape, { strokeWidth: 3, stroke: "#555", strokeDashArray: [10, 5] }, // this shape is the link itself
          new go.Binding("strokeDashArray", "ownership_strokedash")
        ),
        $$(go.Shape, { toArrow: "" }, // this shape is the arrowhead
          new go.Binding("toArrow", "to_arrow"),  // to_arrow = "Standard"
          new go.Binding("fill", "arrow_fill_color"),
        ),
        $$(go.Panel, "Auto", {  }, // this whole Panel is a link label
          $$(go.Shape, "RoundedRectangle", { fill: "lightgray", stroke: "gray" },
            new go.Binding("fill", "ownership_fill_color"),
            new go.Binding("stroke", "ownership_border_color"),
            new go.Binding("strokeWidth", "ownership_border_thickness"),
          ),
          $$(go.TextBlock, { margin: 3 },
            new go.Binding("text", "amount"),
            new go.Binding("stroke", "ownership_font_color"),
            new go.Binding("font", "ownership_font"),)
        )
      );

Here’s my code for the diagram, which determines the location of the link panel based on how many links are coming out of / going into the node:

myDiagram =
      $$(go.Diagram, "myDiagramDiv",
        {
          initialContentAlignment: go.Spot.Center,
          initialAutoScale: go.Diagram.UniformToFill,
          layout: $$(go.LayeredDigraphLayout,
            { direction: 90, layerSpacing: 100, layeringOption: go.LayeredDigraphLayout.LayerLongestPathSource }),
            "LayoutCompleted": function(e) {
              // Push all link panels to the very beginning of the link (close to the bottom of the parent) as a starting point to be adjusted below
              e.diagram.links.each(function(l) { l.elt(1).segmentIndex = -Infinity; });
              // loop through every node on the diagram
              e.diagram.nodes.each(function(n) {
                // get all of the links that leave from the node
                var outLinks = n.findLinksOutOf();
                // count the number of links leaving the node
                var numOuts = outLinks.count

                // if there are any links leaving the node, style the link based on the following cases:
                if (numOuts > 0) {
                  
                  outLinks.each(function(link) {
                    // follow the link to it's destination node and determine how many total links are entering this destination node
                    var subsNumOfIns = link.toNode.findLinksInto().count

                    if(numOuts === 1 && subsNumOfIns === 1) {
                      // if the link is the only one out of the parent and the only one into the sub, put the label halfway along the link
                      link.elt(1).segmentIndex = NaN;
                      link.elt(1).segmentFraction = 0.5;
                    } else if (numOuts === 1 && subsNumOfIns > 1) {
                      // if the link is the only one out of the parent but one of many into the sub, put the label right below the parent
                      link.elt(1).segmentIndex = 1;
                    } else if (numOuts > 1 && subsNumOfIns === 1) {
                      // if the link is one of many out of the parent but the only one into the sub, put the label right above the sub
                      link.elt(1).segmentIndex = -2;
                    } else if (numOuts > 1 && subsNumOfIns > 1) {
                      // if the link is one of many out of the parent and one of many into the sub:
                        if(link.toNode.position.y - link.fromNode.position.y < 225) {
                        // if only one row apart (i.e. less than 175 points on the coordinate plane apart)
                          // make the links straight lines (e.g. "Normal") instead of orthagonal
                          link.routing = go.Link.Normal
                          // remove the end segment lenths (the vertical portions of the links immediately above/below nodes)
                          link.fromEndSegmentLength = 0;
                          link.toEndSegmentLength = 0;
                          // have the link label appear 1/4 of the way along the straight line or 40% along if there are more than 3 outs from the entity (to give more space)
                          link.elt(1).segmentIndex = NaN;
                          if(numOuts <= 3) {
                            link.elt(1).segmentFraction = 0.25;
                          } else {
                            link.elt(1).segmentFraction = 0.4;
                          }
                        } else {
                        // if more than one row apart (i.e. more than 175 points on the coordinate plane apart)
                          // style this differently - for now just leave it as orthagonal
                        }
                    }
                  });
                }
              });
            },
          "undoManager.isEnabled": true
        }
      );

Here’s how it is showing:

How can I position the arrows at the very end of each link (closest to the “To” node) without messing up the positioning of the link panels, which is working as I’d like? Thank you!

By default, the toArrow arrowheads are at the end of the Link. But your code in the "LayoutCompleted" Diagram event is modifying those arrowheads. I think you mean for it to modify the link label panel instead.

In your code you have link.elt(1) to mean the label (according to comments), but this is actually the arrowhead that you are adjusting, because your Link template is essentially:

go.Link
  Shape - this is elt(0), the link's path
  Shape - this is elt(1), the arrowhead
  Panel - this is elt(2), the label

So I wonder if the only edit you need is to use elt(2) everywhere instead of elt(1). Or else just reorder the GraphObjects inside of your link so that the arrowhead comes last instead of at that position.

Thank you! That makes sense, I recently added the arrowheads and didn’t realize it would change what elt(1) referred to.