Problem with links when tree collapse

i m working on a diagram with base as tree mapper
now there are links in my diagram from node to node

like the one from 1st attribute to column , the problem is when i collapse the table the link goes and joins the group instead of parent how to fix that?

secondely it becoms realy janky when i move the group

Have you looked at the implementation of the Tree Mapper sample?
Does its custom TreeNode class do what you want?
(I do not think you want the custom Link class.)

i m not using the custom link class as i need the links from node to node instead of group to group

what i want is a link behavior as of in groups like when u collapse one group with links its links goes to parent group

Do you see what that sample’s TreeNode class does? It redirects connected links to connect to the first visible tree parent node. Or is that not what you are asking for?

yes that is what i want but it is not doing that in my case how do i define a tree node?
do i do it in template?

this.diagram.nodeTemplate = this.Go(MapperTreeNode, {
  movable: false,
  copyable: false,
  deletable: false,
  textEditable: false
}, // user cannot move an individual node
  // no Adornment: instead change panel background color by binding to
  // Node.isSelected
    contextMenu: // define a context menu for each node
      this.Go("ContextMenu", // that has one button
          this.Go(go.TextBlock, "Load Parent", { margin: new go.Margin(10, 20, 10, 20) }),
            click: (e, obj) => this.checkbeforexpandParent(e, obj)
          new go.Binding("visible", "loadParent", (h) => { return h })
          this.Go(go.TextBlock, "Load Sibling", { margin: new go.Margin(10, 20, 10, 20) }),
            click: (e, obj) => this.checkbeforexpandSibling(e, obj)
          }, new go.Binding("visible", "loadSibling", (h) => { return h })),

        // more ContextMenuButtons would go here
      ) // end Adornment
    selectionAdorned: false
  // whether the user can start drawing a link from or to this node
  // depends on which group it's in
  new go.Binding("fromLinkable", "group", function (k) {
    // return k === -1;
    return false;
  }), new go.Binding("toLinkable", "group", function (k) {
    // return k === -2;
    return false;
  this.Go(go.Panel, "Horizontal", {},
    this.Go(go.Shape, "Rectangle", {
      name: "SHAPE",
      fill: '#009CCC', strokeWidth: 0, stroke: '#009CCC',
      width: 3, stretch: go.GraphObject.Vertical, alignment: go.Spot.Left,
    this.Go(go.Panel, "Auto", { stretch: go.GraphObject.Horizontal },
      this.Go(go.Shape, "Rectangle", {
        name: "mainSHAPE",
        fill: "#ffffff", stroke: '#CCCCCC', strokeWidth: 0,
        fromSpot: go.Spot.RightSide,
        toSpot: go.Spot.LeftSide,
      this.Go(go.Panel, "Table",
        { stretch: go.GraphObject.Horizontal, minSize: new go.Size(150, 20) },
            column: 0,
            name: "GROUPTEXT",
            margin: new go.Margin(8, 0, 8, 4), font: Constants.attributefont, editable: true,
            maxLines: 1, isMultiline: false,
            stroke: "#686868",
            alignment: go.Spot.LeftCenter

          new go.Binding("text", "text").makeTwoWay()),

          "assets/treeImages/downbebebe.png", {
          column: 1,
          name: "Expand",
          alignment: go.Spot.Right, angle: 180,
          click: (e: any, obj: any) => this.expandTree(e, obj),
          //transition image
          // mouseEnter: (e, obj, prev) => {
          // var shape = obj.part.findObject("Edit");
          // if (shape instanceof go.Picture) {
          // shape.source = "assets/treeImages/edit.png";
          // }

          // },
          // mouseLeave: (e, obj, next) => {
          // var shape = obj.part.findObject("Edit");
          // if (shape instanceof go.Picture) {
          // shape.source = "assets/treeImages/edit.png";
          // }
          // },
          background: "transparent",
          margin: new go.Margin(0, 8, 0, 20),
          desiredSize: new go.Size(12, 8)
  ), // end Horizontal

  // Panel
); // end Node

that is my node template and this is the class

export class MapperTreeNode extends go.Node {
  constructor() {
if (this instanceof go.Node)
  this.treeExpandedChanged = function (node) {
    if (node.containingGroup !== null) {
      node.containingGroup.findExternalLinksConnected().each(function (l) {


But your class does not include the override of Node.findVisibleNode!

doing that doesnot work if it has 2 parents that is not imediate

it is only working if i do it step by step
Screenshot from 2020-03-02 17-06-12

MapperTreeNode.prototype.findVisibleNode = function() {
  // redirect links to lowest visible "ancestor" in the tree
  var n = this;
  while (n !== null && !n.isVisible()) {
    n = n.findTreeParentNode();
  return n;

this is what i did in my init function

I thought your situation is the same as what the Tree Mapper sample demonstrates. When you compare your app with the Tree Mapper sample, what are the meaningful differences? (Just relating to this specific issue, of course.)

it is kind of the same as tree mapper the difference is that the link are connected to node instead of groups but the link functionality is not working like in the sample, the other difference is that i m using angular

another difference is that i load parents dynamicallyScreenshot from 2020-03-02 17-37-47

Those differences don’t seem relevant, but it’s hard to say. I can look into this later today, but I’m not sure what I can do to reproduce the problem. Could you create an absolute minimal test case? Use the minimum data and the simplest templates possible, regardless of appearances. That means one Node template, one Group template, and one Link template.

will do within the hour

Sent the code in email

I have received the code. Thank you. It isn’t minimal, so I will look at it later when I have more time.

Ah, there seems to be a problem computing the link connection points and directions when findVisibleNode returns a different Node and the spot is a “…Side” Spot. This will require further investigation.

Meanwhile you can temporarily avoid the problem by using specific spots, such as by replacing:
fromSpot: go.Spot.LeftRightSides, toSpot: go.Spot.LeftRightSides,
fromSpot: go.Spot.Right, toSpot: go.Spot.Left,

Thanks for reporting the problem.