Link Location in Tree Layout

Could you look in the debugger at the Link that connects to the child/Group? I’m wondering why its Link.toSpot isn’t Top.

You can do it by selecting that Link and evaluating something like:

myDiagram.selection.first().toSpot.toString()

It should return “Spot(0.5,0)”.

Once i invisible the “Circle” Shape mentioned before, the link connects to the top ,of the group, yet it is in front of all elements, i need to push the link “behind” the group.
Tried zOrder the link to -100.
Didn’t help.

Sorry, we cross-posted, so I didn’t read your post mentioning a “Circle” Shape.

I don’t understand the purpose of that “Circle” Shape. Is its GraphObject.portId set to the empty string?

All of the visual tree of a Group is drawn with the same z-ordering as the Group itself. Each of the members of the Group can have a z-ordering different from the Group – they are independent Parts.

yes this Shape has portId: “”.
I tried to set the Link zOrder to -100, but it didnt send the link behind the group

Part.zOrder only controls the ordering within a Layer. What layers are the Link and the Group in? If they are in the same layer, what is the Group’s zOrder?

I set group zOrder to 1 and the link zOrder to 0 and the link went behind. Now i need to eliminate the “Circle” Shape from the template, namely delete it when running the TreeLayout.
Any way to delete an object (Shape) within on object ?
I tried
obj = group.findObject(“linkConnector”)
groupt.remove(obj);

Didn’t work

Would you mind sharing your group template? That may help us better understand how to simplify your groups to achieve what you want. What happens if you just remove the “Circle” shape from the template?

If i remove the “Circle” object from the template, it works fine.
Here is the Group template :

defaultGroupTemplate(that) {
    var GO = that.GO;
    var x =
      GO(go.Group, "Auto",   // Header and group members panel one below each other
        {
          isSubGraphExpanded: false,
          ungroupable: true,
          background: "white",
          mouseOver: function (e, node) { node.isShadowed = true; },
          mouseLeave: function (e, node) { node.isShadowed = node.isSelected; },
          doubleClick: function (e, node) { that.diagram.commandHandler.expandSubGraph(node); },
          toolTip: that.siteTooltip(GO)
        },
        new go.Binding("scale", "groupPictureScale").makeTwoWay(),
        new go.Binding("position", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
        new go.Binding("isSubGraphExpanded").makeTwoWay(),
        new go.Binding("isShadowed", "isSelected", function (s) { return s; }).ofObject(),

        GO(go.Shape, "RoundedRectangle",
          {
            fill: "transparent",
            isPanelMain: true,
            stroke: that.CONST_GROUP_BORDER_COLOR,
            strokeWidth: CONST_GROUP_BORDER_WIDTH
          },
            new go.Binding("stroke", "statusColor"),
           new go.Binding("opacity", "groupMonitoringOpacity"),
        ),

        // Panel for holding COLLAPSED Group Header info
        GO(go.Panel, "Vertical",
          GO(go.Panel, "Table",
            {
              stretch: go.GraphObject.Horizontal,
              background: "#124386",
            },

            //  Panel for implementing our own  custom SubGraph Expander Button
            GO(go.Panel, "Spot",
              { column: 0, },
              new go.Binding("visible", "isSubGraphExpanded", function (s) { return s; }).ofObject(),
              GO(go.Shape, "Rectangle",
                {
                  desiredSize: new go.Size(34, 34),
                  fill: "#124386",
                  //stroke: "white",
                  stroke: that.CONST_GROUP_BORDER_COLOR,
                  click: function (e, node) { that.diagram.commandHandler.collapseSubGraph(node); }
                },
              ),
              GO(go.Shape, "Rectangle",
                {
                  desiredSize: new go.Size(10, 2),
                  fill: "white",
                  stroke: "transparent",
                  alignment: go.Spot.Center,
                  click: function (e, node) { that.diagram.commandHandler.collapseSubGraph(node); }
                },
              )
            ),
            // group name in Header
            GO(go.TextBlock,
              {
                column: 1,
                font: "bold 14pt rubikregular",
                editable: false,
                stroke: "white",
                margin: 2,
                verticalAlignment: go.Spot.Center,
                textAlign: "center",
                stretch: go.GraphObject.Horizontal,
              },
              new go.Binding("text", "groupName").makeTwoWay(),
              new go.Binding("editable", "isAutomaticGroup", function (val) { return !val; }),
            ),
            new go.Binding("stroke", "statusColor")
          ),  // Horizontal Panel

          // Panel for Holding Group Info (name, icon, site) and place holder
          GO(go.Panel, "Auto",
            { width: 100, height: 150 },
            new go.Binding("visible", "isSubGraphExpanded", function (s) { return !s; }).ofObject(),
            GO(go.Panel, "Spot",
              // a Dedicated "hidden" shape (height=0) to enable connection between collapsed group links.
              GO(go.Shape, "Circle",
                {
                  height: 0,
                  portId: "",
                  stretch: go.GraphObject.Horizontal,
                  name: "LinkConnectorShape"
                }
              ),
              // The portId serves as the link connector
              GO(go.Panel, "Vertical",
                {
                  alignment: go.Spot.Top,
                  minSize: new go.Size(90, 80)
                },
                // Group Icon
                GO(go.Picture, {
                  scale: 0.9,
                  margin: new go.Margin(20, 0, 0, 0)
                },
                  new go.Binding("source"),
                ),
                // operAssociation - שיוך מבצעי
                GO(go.TextBlock,
                  {
                    font: that.CONST_DEFAULT_FONT,
                    editable: false,
                    wrap: go.TextBlock.WrapFit,
                    textAlign: "center",
                    width: 90,
                    margin: new go.Margin(10, 0, 0, 0)
                  },
                  new go.Binding("text", "operAssociation"),
                  new go.Binding("visible", "operAssociation", function (s) { return (s != null && s != ''); }),
                ),
                // group address
                GO(go.TextBlock,
                  {
                    font: that.CONST_DEFAULT_FONT,
                    editable: false,
                    wrap: go.TextBlock.WrapFit,
                    textAlign: "center",
                    width: 90
                  },
                  new go.Binding("text", "address"),//IDO changed from groupName
                  new go.Binding("visible", "address", function (s) { return (s != null && s != ''); }),
                ),
                // Quality Message
                GO(go.TextBlock,
                  {
                    font: that.CONST_DEFAULT_FONT,
                    editable: false,
                  },
                  // if mobile and has modem with rx quality - show in group
                  new go.Binding("visible", "siteMobilityCode", function (siteMobilityCode, obj) {
                    if (obj["part"].data.networkType == undefined)  // show site type for site group only
                      return (siteMobilityCode != null && siteMobilityCode == 1);
                    else
                      return false;
                  }),
                  new go.Binding("text", "rxQUalityMsg"),
                  new go.Binding("stroke", "rxTextColor")
                ),
              ),
            ),
            // if mobile and has modem with rx quality - show rxquality icon in group
            GO(go.Picture, {
              scale: 1.4,
              alignment: go.Spot.TopRight,
            },
              new go.Binding("visible", "siteMobilityCode", function (siteMobilityCode, obj) {
                if (obj["part"].data.networkType == undefined)  // show site type for site group only
                  return (siteMobilityCode != null && siteMobilityCode == 1);
                else
                  return false;
              }),
              new go.Binding("source", "rxQUalityIcon", function (q) {
                let icon = "";
                var qualityString = ['', 'week', 'poor', 'good', 'best'];
                if (q > 0)
                  icon = 'rx_quality_' + qualityString[q] + '.svg';
                return NetMapDiagramComponent.CONST_ICON_RELATIVE_PATH + icon;
              })
            ),
            // Site Status -
            // (show this textbox only if site status is NOT KAYAM)
            GO(go.TextBlock,
              {
                visible: false,
                background: 'rgba(0,0,0,0.4)',
                height: 25, width: 100,
                textAlign: 'center',
                font: "bold 13pt rubikregular",
                stroke: '#fff',
                verticalAlignment: go.Spot.Center
              },
              new go.Binding("visible", "statusCode", function (statusCode, obj) {
                // if the group type if of NetworkType or User, dont show the status (visible=false)
                if (obj["part"].data.networkType != undefined || statusCode == undefined)
                  return false;
                else
                  // the group is of site with site status code. Show the status only of statusCode NOT KAYAM(0)
                  return statusCode != 0;
              }
              ),
              new go.Binding("text", "statusCode", function (statusCode, obj) {
                // show the value of group type of Site only and only is statusCode exists
                if (obj["part"].data.networkType == undefined && statusCode != undefined) {
                  var statusString = ['קיים', 'בפירוק', 'בהקמה', 'בדילוג', 'לא פעיל'];
                  return statusString[statusCode];
                }
              })
            )  // textblock
          ),
          // Panel for holding Group members
          GO(go.Panel, "Auto",
            new go.Binding("visible", "isSubGraphExpanded", function (s) { return s; }).ofObject(),
            GO(go.Placeholder, // represents area for all member parts
              { background: "transparent", margin: 10 },
            )  // Place holder
          )  // Auto
        ) // Auto
      );
    return x;
  }

If you are going to delete the apparently unnecessary “Circle” Shape, you should delete the “Auto” Panel that is using that shape as the border around the rest of the elements of that panel.

In general there should not be any “Auto” or “Spot” Panels that have zero or only one element in them – they should have two or more elements. I notice that you have an “Auto” Panel surrounding only a Placeholder – you can probably remove that “Auto” Panel and leave just the Placeholder.

Ok, Understood.
So, how can I delete the “Circle” Shape ?
It pushes the link behind the group. I want the link to connect to the Top of the group node.

Please format your code by surrounding your block of code with lines consisting of triple-backquote: Code Formatting

Even when your code is formatted, it’s too long for me to understand its structure without taking a lot of time to read it.

Basically, if your structure is:

. . .
  Panel
    Panel, "Spot"
        Shape, "Circle"
        (any element)

you can remove the Circle Shape by removing that Shape and its containing “Spot” Panel:

. . .
    Panel,
        (any element)

You will probably want to move any properties and Bindings that were on the excised “Spot” Panel to the remaining (any element).

I’m not sure i’m clear.
The “Circle” shape is contained in an “Auto” panel.
I cannot remove the “Auto” panel since it has lots of other panels.
Maybe i can create a “dummy” “Auto” panel and place the “circle” in it, and then, delete the “Auto” shape…

What is the purpose of that particular “Spot” Panel if it no longer has its main element (the zero height Circle Shape)?

If you say just deleting the Circle Shape leaves the whole Group working well, why are we having this conversation?

I’m using this template for network diagram that connects telecom links and nodes.
I’m implementing a function that transform the network layout into tree layout.
When i go into tree layout, i need to “hang” the group node under the a parent node but maintain its template.
So, in order to hang the group node properly , i would like to delete the “Circle” shape.

If you don’t want it to be seen, you have several choices:

  • set Shape.fill to null and Shape.strokeWidth to 0
  • set its opacity property to 0.0
  • set its visible property to false, although this might change the link connection behavior

Since you don’t really need this Circle Shape to be the default port, I would remove the portId: "" assignment.

OK,
i tried :
var partInGroup = part.findObject(“someName”);
delete partInGroup.portId

Didn’t help…

So i did
partInGroup.portId=“dddd”;

Bingo !!!

No, I was suggesting that you change your template not to set portId at all.

But i need this type of connection (links behind nodes) for the network layout.

In general one should not be modifying the portId of an element dynamically. I suppose in this situation it might happen to work.

I see,
I will try to avoid that in future use cases.
Nevertheless, it is for me the “cheapest” way to use the group template for tree layout and network layout.
Thanks for the support.