Hide panel if all contained rows are invisible

I have a panel (let’s call it “PanelA”) of type auto with a border and a TablePanel with multiple rows.
The visibility of the rows if defined through a binding, e.g. it can happen that all rows are invisible.
Currently the border is displayed even if all rows are invisible.

How can I hide (i.e. set the visible property to false) PanelA if all rows of the contained TablePanel have visible = false?

I tried accessing the tablePanel.rowCount, but this is always 0?!

So you have the Panel.itemTemplate being a “TableRow” Panel that has a Binding of “visible”?

Yes exactly.

<!DOCTYPE html>
<title>Minimal GoJS Sample</title>
<!-- Copyright 1998-2019 by Northwoods Software Corporation. -->
<meta charset="UTF-8">
<script src="https://unpkg.com/gojs"></script>
<script id="code">
  function init() {
    var $ = go.GraphObject.make;

    myDiagram =
      $(go.Diagram, "myDiagramDiv",
          { "undoManager.isEnabled": true });

    myDiagram.nodeTemplate =
      $(go.Node, "Vertical",
        $(go.TextBlock, new go.Binding("text")),
        $(go.Panel, "Auto",
          new go.Binding("visible", "show"),
          $(go.Shape, { fill: "lightyellow" }),
          $(go.Panel, "Table",
            new go.Binding("itemArray"),
                $(go.Panel, "TableRow",
                  new go.Binding("visible"),
                  $(go.TextBlock, { margin: 4 },
                    new go.Binding("text")),
                      column: 1,
                      click: function(e, button) {
                        toggleVisible(e.diagram.model, button.part.data, button.panel.data);
                    $(go.TextBlock, "X")

    function toggleVisible(model, nodedata, itemdata) {
      model.commit(function(m) {
        var vis = itemdata.visible !== false;
        m.set(itemdata, "visible", !vis);
        var show = false;
        var arr = nodedata.itemArray;
        // check all items, assume undefined means "visible"
        arr.forEach(function(d) {
          if (d.visible === true || d.visible === undefined) show = true;
        m.set(nodedata, "show", show);

    myDiagram.model = new go.GraphLinksModel(
        key: 1, text: "ONE", 
        show: true,
        itemArray: [
          { text: "A", visible: true },
          { text: "B", visible: false },
          { text: "C" },
        key: 2, text: "TWO",
        itemArray: [
          { text: "AA", visible: true },
          { text: "BBBB", visible: false },
          { text: "CCCCCC" },
      { from: 1, to: 2 }
<body onload="init()">
  <div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:600px"></div>

Is it necessary to have the show property on the top-level or can I somehow bind the AutoPanel visibility directly to the TableRow visible properties…?

Bindings cannot directly cross between binding contexts. An itemTemplate has its own binding context.

You could change the toggleVisible code to operate on a Diagram, a particular Node, and a particular item Panel within that node, rather than on a Model, a node data object, and an item data object. But that would prevent manipulation of the model independently of the diagram.

Shouldn’t it be possible to bind the visible attribute to the rowCount of the table panel?
I tried, but it doesn’t work, rowCount seems to be 0:

new go.Binding("visible", "rowCount", (rowCount) => rowCount === 3).ofObject("tableA")

Is this conceptually not working or is there just a mistake in my code?

I think Panel.rowCount is zero at the time that Bindings are being evaluated. After all, the Table Panel might need to measure and arrange itself differently based on the property values it gets via bindings.

Also, such Binding source properties must be settable; rowCount is read-only.

I see, thanks for the explanation!