Can expand/collapse button be used with Double tree?

I built a double tree (with right , left and top parts )using Double tree sample , I have got this one as shown in the image below

But I am wondering if I can use expand/collapse buttons to hide and show the nodes in both right and left sides, I tried many times but with no luck . It seems based on my findings that the expand/collapse buttons just work with Graplinksmodel , is this right ?

Kindly note that I used TreeModel with Double tree layout as implemented in the sample. Please help me with this. Thanks in advance.

I did the minimum work to add a “TreeExpanderButton” to the node template in the Double Tree sample, and it worked well:

    myDiagram.nodeTemplate =
      $(go.Node, "Vertical",
        { isShadowed: true },
        $(go.Panel, "Auto",
          // define the node's outer shape
          $(go.Shape, "RoundedRectangle",
            { fill: graygrad, stroke: "#D8D8D8" },
            new go.Binding("fill", "color")),
          // define the node's text
            { margin: 5, font: "bold 11px Helvetica, bold Arial, sans-serif" },
            new go.Binding("text", "key"))

I’m curious what you tried that didn’t work. No matter how you add the “TreeExpanderButton”, it should work as long as the user can click on it.

finally it works , the root cause was that I added this statement to the code “myDiagram.isReadOnly = true;”
Thank you so much, your efforts are appreciated.

I have 4 questions as marked in the image below

Question #1 :
Can I have two buttons in the root node , to expand / collapse right and left parts separately ???

Question # 2:
Can I have the button just on the leaf nodes to hide the “control1” node and have the “Threat1” node visible ??

Question # 3 :
How to change the position of the button to be not centered on the node , such as to be on the top left corner ???

Question # 4:
I am working on generating a Bowtie diagram , do you support this feature on your library as a sample ???
Thanks in Advance

1: Yes, but you can’t use a “TreeExpanderButton”, since it doesn’t know that you want to distinguish some children from others. Use a regular “Button”: GoJS Buttons -- Northwoods Software. Add a property to the root node’s data representing whether a side is collapsed – I’ll use isCollapsedRight:

            name: "ButtonIcon",
            figure: "MinusLine",
            desiredSize: new go.Size(6, 6)
          new go.Binding("figure", "isCollapsedRight",  // data.isCollapsedRight remembers whether "collapsed"
                         function(collapsed) { return collapsed ? "PlusLine" : "MinusLine"; })),
          click: function(e, obj) {
            var node = obj.part;
            var collapsed = !;  // toggle collapse state
            // remember collapse state on root data, with support for bindings and undo
            e.diagram.model.setDataProperty(, "isCollapsedRight", collapsed);
            // collapse/expand immediate children and toggle their visibility
            node.findLinksOutOf().each(function(n) {
                if ( === "right") {  // just nodes on the right side of tree
                    n.visible = !collapsed;
                    n.isTreeExpanded = !collapsed;
            e.diagram.commitTransaction("toggled visibility of consequences");

Caution: I haven’t tried this code.

2: Yes, you can put buttons on just those nodes that you want, but what would that mean when there are branches in the subtree?

3: Learn about Panels: GoJS Panels -- Northwoods Software and GoJS Table Panels -- Northwoods Software

4: Perhaps you would be interested in this sample: Minimal GoJS Sample

I highly recommend that you carefully read all of Get Started with GoJS and all of the Introduction pages that apply to the kind of app that you want to build, at GoJS Introduction -- Northwoods Software.

I am working on generating a Bowtie Diagram ,so we need to show just the main nodes that are Threats and Consequences , while have their controls hidden or shown using collapse / expand.

Thank you very much Walter , I really appreciate your efforts :)

Ah, that would be a completely different kind of “collapse”/“expand”. If I understand what you are saying, you want to hide all of the intermediate nodes between the root and a leaf node. The normal “tree expand/collapse” (whose state is implemented by Node.isTreeExpanded) shows/hides all of the node’s tree children and all of their children, recursively.

But you still want to show some sort of link between the root and that leaf node? I’ll assume so.

So I would implement that using a different “Button”, since yet again you cannot use the existing “TreeExpanderButton”. In this case I would make all of the intermediate nodes not visible, and I would create/make-visible a direct link from the root node to that leaf node. “Expanding” would do the opposite.

If you are using a TreeModel, one way to do that would be to change the leaf node’s data’s parent by calling TreeModel.setParentKeyForNodeData. I suppose you’ll want to save the original intermediate node’s key so that you can restore it when expanding.

Hmmm, when collapsing you’ll first want to walk the chain of Node.findTreeParentNode before you modify the leaf node’s parent to be the root node. Similarly, when expanding, you’ll want to change the parent and then you can walk the parent chain to make those nodes visible.

Remember to make all changes within a single transaction.

1 Like

Another question please : The added button is added to all Nodes ! How to show the button on some specific nodes such as root and leaf nodes ?

Thanks in advance

Either bind GraphObject.visible on the “Button”, or use different templates (GoJS Template Maps -- Northwoods Software).

As you can see in the definition of the “TreeExpanderButton”, one Binding source can be “isTreeLeaf” when Binding.ofObject().

Another question please : I want to retrieve all nodes’ keys between the Root node and the leaf one , so I can hide/ show them using expand /collapse code I wrote as we discussed in previous questions. Is there an API to achieve that ?! I searched for an API but with no luck. Please advise

Thanks in advance

In version 1.7 (currently in alpha test) we have added a new method: Node.findTreeParentChain. Here is its documentation:

Return a collection of Parts including this Node,
its tree parent link and node, and so on up the chain to the root node.

This calls findTreeParentLink and findTreeParentNode.
Links for which Link.isTreeLink is false are ignored.

The result will include this node and the “root” node and all nodes and links in between.
The root node is also accessible directly via findTreeRoot.
If any of the nodes are Groups, their member parts are not included.

See also: findTreeRoot findTreeParts

Returns:{Set.} A Set of Nodes and Links.

For now, though, you’ll need to implement this yourself. Maybe something like:

function findTreeParentChain() {

  function addParent(n, coll) {
    if (n === null) return;
    var l = n.findTreeParentLink();
    if (l !== null) {
      addParent(n.findTreeParentNode(), coll);

  var set = new go.Set(go.Part);
  addParent(this, set);
  return set;

I suppose you could use this and not bother to accumulate the Links, if you don’t need them.

I called this API , but the retrieved object is weird !! as shown below in the snapshot

how can I retrieve nodes’ keys form it !!!

Thank u so much Walter :)

I think you need to read the Introduction pages, at GoJS Introduction -- Northwoods Software. Read especially:
GoJS Collections -- Northwoods Software
GoJS Using Models -- Northwoods Software
GoJS Data Binding -- Northwoods Software
But I recommend that you read all of the other pages too.

And you need to read and understand the function I just gave you.

Another question please:
I am trying to read the node’s location of Control1 Node as illustrated below

because I want to shift the node1 when collapsing to be on Control1 node’s position as shown below:

the location is retrieved undefined!!! , can the location be read when using Tree Model (Double Tree layout is used ) ???

Are you looking at the Node.location? I’m certain that that property value will be a Point.

Maybe you are looking at the model’s node data for that Node? If so, it will have a location only if you have established a TwoWay Binding on Node.location with some property that you have named in the Binding.

Also, if you perform the layout again, I’m confident that “node1” will be moved where you are expecting it to be, where “Control1” used to be.

But that requires that links are going in the expected direction. That seems not to be the case now if you are using a “TreeExpanderButton” on “node1”. I would have expected that the “root” node is the root of all trees. By default the links should be going from the parent node to the children nodes. If you do not want that to be the case, you can set Diagram.isTreePathToChildren to false. Of course you will need to make sure then that all links go from a child node to a parent node.

I have already defined a TwoWay Binding on Node.location but with no luck but I will give this another try . Regarding the button it is a custom button with a custom code I wrote to achieve an expand/collapse operation differ than the normal operation supported by the library.

I thought I’d jump into this conversation because I have a very similar question to Reema’s original title + question.

I am using pretty much the exact implementation of DoubleTree from the sample (although in version 1.6.22 no latest), and I would like to add TreeExpander buttons.

I had no trouble adding the buttons, and the expansions are working fine. However, I noticed that unlike most other situations that the TreeExpander is used, in DoubleTree the tree does not automatically resize on expand + collapse.

I believe this is due to the arrangement of each layout being ArrangementFixedRoots, however, any attempt to change the layout results in a very messed up diagram. Any thoughts on how I can preserve the look of ArrangementFixedRoots, but resize the diagram one expand + collapse?

That’s because there isn’t a Diagram.layout that is responsible for laying out the whole diagram – it’s implemented by two (or more?) instances of TreeLayout that are invoked programmatically.

So I’ve implemented such a custom Layout, in [EDIT: obsolete, now in extensions/].

Hello, Walter,

Great Works!!!
I hava a huge tree (from DB) and when collapsed, it looks not-densed, and it has been a problem for more than 2weeks!
but with your new DoubleTreeLayout, it works well like picture attached.
([EDIT: obsolete, now in extensions/]).

By the way, why don’t you update your doubletree.html in yout sample (Double Tree and DoubleTree JSON) It looks like old sourcecode some one asked for above.

Thanks again!!

Thanks. Yes we should.