Accessing Panel expander button functionality programatically

Hi,
I have a panel expander button on all the nodes in my diagram. When I click on the button, my node expands to display another panel. I have implemented it as follows:

$("PanelExpanderButton", "PROPTEXT",
                    {
                        row: 2, column: 2,
                        margin: new go.Margin(0, 0, 10, 0),
                        'ButtonBorder.fill': 'white', '_buttonFillOver': 'white',
                        '_buttonStrokeOver': 'white',
                        click: (e, btn) => {
                            var diagram = btn.diagram;
                            if (diagram === null) return;
                            if (diagram.isReadOnly) return;
                            var elt = btn.findTemplateBinder();
                            if (elt === null) elt = btn.part;
                            if (elt !== null) {
                            var pan = elt.findObject('PROPTEXT');
                            if (pan !== null) {
                                diagram.startTransaction('Collapse/Expand Panel');
                                pan.visible = !pan.visible;
                                diagram.commitTransaction('Collapse/Expand Panel');
                            }
                            }
                            e.handled = true;
                        },
                        background: 'white'
                    },
                    go.GraphObject.make(go.Shape,
                        { name: 'ButtonIcon', 
                            fill: '#10069f', 
                            stroke: '#10069F', 
                            strokeWidth: 1, 
                            width: 10, 
                            height: 7,
                            background: 'white',
                        },
                        new go.Binding('geometryString', 'visible',
                        (vis) => { return vis ? 'F M24.642,18.124l-1.768,1.768L16,13.017,9.124,19.892,7.357,18.124,16,9.481Zm0,0' : 'F M24.642,13.874l-1.768-1.768L16,18.981,9.124,12.106,7.357,13.874,16,22.517Zm0,0' }
                        ).ofObject('PROPTEXT')
                    )
                ),

Now, I want to have a toggle switch using which I can expand/collapse the PROPTEXT panels of all the nodes that are present in my diagram.

How can this be done?

Within a single transaction, iterate over all of the Diagram.nodes. Skip over any nodes that are of the kind that would not have that panel. Call findObject("PROPTEXT") and if it returns the desired Panel, set its visible property.

Hi,

This is my implementation:

openPropTextOnCommit(key) {
    let model = this.diagram.model;
    model.startTransaction('propTextView');
    this.diagram.findNodeForKey(key).findObject("PROPTEXT").visible = true;
    model.commitTransaction('propTextView');
}

It works fine, but there’s one issue. Lets say there are 4 nodes in my diagram with the PROPTEXT panels visible. If this function is called for node 2, it causes all the other nodes to close the PROPTEXT panels, and keeps only node2’s panel visible.

How can I prevent this behaviour? I dont want a change in one node’s panel, to affect visibility of other nodes panels.

My initial reaction was that that was impossible, since setting a property on one GraphObject only changes that GraphObject (unless you had gone to some trouble to implement exactly that) and GraphObjects are not shared between different Panels, and thus not shared between different Nodes.

But then it occurred to me that you probably had a TwoWay Binding on the “visible” property of that “propTextView” object. So one possibility is that the object in the model holding that binding’s source property is being shared by different nodes. Could you please check in the debugger if that is true for nodes 2 and 1?

If that object is indeed shared by all four nodes, then you need to make sure that each node’s data in the model no longer shares that object. You may need to set https://gojs.net/latest/api/symbols/Model.html#copyNodeDataFunction. Or maybe https://gojs.net/latest/api/symbols/Model.html#copiesArrays and https://gojs.net/latest/api/symbols/Model.html#copiesArrayObjects.

Im not using TwoWay binding on the visible property. This is the definition of the PROPTEXT panel:

$(go.Panel, 'Vertical',
                {
                    row: 2, column: 1, name: 'PROPTEXT',
                    width: 205,
                    visible: false,
                    margin: new go.Margin(-1, -1.5, 0, 35)
                },
                $(go.Panel, 'Auto',
                    {
                        width: 205
                        
                    },
                    $(go.Shape, 'RoundedBottomRectangle', {
                        stroke: '#8f9999',
                        strokeWidth: 1,
                        fill: '#f0f2f2',  // default color,
                        alignment: go.Spot.Left
                    }),

                    $(go.Panel, "Table",
                        new go.Binding("itemArray", '', (data) => {
                            
                            const array = Object.entries(this.propertiesInfo(data));
                            for (let index = 0; index < array.length; index++) {
                                const element = array[index];
                                if (element[0] == '__gohashid') {
                                    array.splice(index, 1);
                                }
                            }
                            return array;
                        }),
                        {
                            stretch: go.GraphObject.Horizontal,
                            itemTemplate:
                                $(go.Panel, "TableRow",
                                    $(go.TextBlock,
                                        {
                                            column: 0, alignment: go.Spot.Left,
                                            font: '12px Noto Sans',
                                            stroke: '#6d7777',
                                            margin: new go.Margin(5, 5, 5, 5),
                                            maxLines: 1,
                                            overflow: go.TextBlock.OverflowEllipsis
                                        },
                                        new go.Binding("text", '', (data) => {
                                            return data[0];
                                        })),
                                    $(go.TextBlock,
                                        {
                                            column: 1, alignment: go.Spot.Right,
                                            font: '12px Noto Sans',
                                            stroke: '#000000',
                                            margin: new go.Margin(5, 5, 5, 0),
                                            maxLines: 1,
                                            overflow: go.TextBlock.OverflowEllipsis,
                                            stretch: go.GraphObject.Horizontal,
                                            textAlign: 'right'
                                        },
                                        new go.Binding("text", '', (data) => {
                                            return data[1];
                                        }))
                                )
                        }),
                )
            )

My theory was a stretch because it seemed that the shared data object had the opposite value for all of the other nodes.

So, I have no idea why you are getting that behavior. If I were you, I would review all of the event handlers and listeners and all of the rest of your code to make sure they are only operating on the nodes and node data that you expect.