Scrolling table not sizing to parent table width

I am trying to get a scrolling table to work inside of another table. But when I add the scrolling table inside, I seem unable to get the scrolling table to match the width of its parent table.

image

What I am trying to accomplish is on the left, and what I am currently getting in on the right.
I need to keep the header row (with Field Name and DataType headers) from scrolling so I have created the below template to try achieve this:

public static createViewNodeTemplate(
        onClicked: (e: go.InputEvent, obj: go.Node) => void
    ): go.Node {

        return Make(go.Node, 'Auto',
            {
                name: 'entityNode',
                cursor: 'pointer',
                selectionAdorned: false,
                zOrder: 1,
                click: (e: go.InputEvent, obj: go.Node) => onClicked && onClicked(e, obj)
            },
            new go.Binding('location', 'location', go.Point.parse),
            Make(go.Shape, 'RoundedRectangle',
                {
                    name: 'entityShape',
                    stroke: Palette.unselectedColour,
                    strokeWidth: 0.5,
                    parameter1: 2,
                    fill: 'white',
                    width: 180
                },
            ),
            Make(go.Panel, go.Panel.Table,
                {
                    name: 'viewEntityMainTable',
                    width: 180,
                    defaultRowSeparatorStroke: 'grey',
                    defaultRowSeparatorStrokeWidth: 0.5,
                },

                Make(go.Panel, go.Panel.TableRow, { row: 0 },
                    // NodeTemplates.createHeaderTable(undefined, undefined, false)

                    Make(go.Panel, go.Panel.Table,
                        {
                            name: 'headerTable',
                            width: 180,
                            background: Palette.entityHeaderColour
                        },

                        Make(go.Panel, go.Panel.TableRow, { row: 0 },

                            Make(go.Panel, 'Auto',
                                {
                                    column: 0,
                                    toolTip: NodeTemplates.createTextBlockTooltip('objectName', 'entityHeaderText')
                                },
                                Make(go.TextBlock,
                                    {
                                        name: 'entityHeaderText',
                                        margin: new go.Margin(8, 2),
                                        alignment: go.Spot.Center,
                                        font: 'bold 7pt sans-serif',
                                        textAlign: 'center',
                                        stroke: Palette.entityTextColour,
                                        overflow: go.TextBlock.OverflowEllipsis,
                                        maxLines: 1,
                                        width: 160
                                    },
                                    new go.Binding('text', 'objectName')
                                )
                            )
                        )
                    )
                ),

                Make(go.Panel, go.Panel.TableRow, { row: 1 },

                    Make(go.Panel, go.Panel.Table,
                        {
                            defaultColumnSeparatorStroke: 'lightgray',
                            defaultColumnSeparatorStrokeWidth: 0.5,
                            defaultRowSeparatorStroke: 'lightgray',
                            defaultRowSeparatorStrokeWidth: 0.5
                        },

                        Make(go.RowColumnDefinition,
                            { column: 0, width: 100 }
                        ),
                        Make(go.RowColumnDefinition,
                            { column: 1, width: 65 }
                        ),
                        Make(go.RowColumnDefinition,
                            { column: 2, width: 15 }
                        ),

                        Make(go.Panel, go.Panel.TableRow, { row: 0 },
                            Make(go.TextBlock, 'FIELD NAME',
                                {
                                    column: 0,
                                    stroke: Palette.entityTextColour,
                                    margin: new go.Margin(5, 3, 3, 8),
                                    font: 'bold 6pt sans-serif'
                                }
                            ),
                            Make(go.TextBlock, 'DATA TYPE',
                                {
                                    column: 1,
                                    stroke: Palette.entityTextColour,
                                    margin: new go.Margin(5, 3, 3, 8),
                                    font: 'bold 6pt sans-serif'
                                }
                            ),
                            Make(go.Panel, 'Auto',
                                {
                                    column: 2
                                }
                            )
                        ),

                        Make(go.Panel, go.Panel.TableRow, { row: 1, columnSpan: 3 },
                            // NodeTemplates.createFieldTable()

                            Make(go.Panel, 'Auto', { column: 0, columnSpan: 3 },
                                Make('ScrollingTable', 'TABLE',
                                    {
                                        // name: 'SCROLLER',
                                        // name: 'fieldTable',
                                        // Create binding to determine the max/desired size, up until 10 items in the field table
                                        // Eg:
                                        // row = 20, rowCount = 5, totalHeight = 100
                                        // row = 20, rowCount = 10, totalHeight = 200
                                        // row = 20, rowCount = 15, totalHeight = 200
                                        desiredSize: new go.Size(NaN, 80),  // fixed width
                                        stretch: go.GraphObject.Fill,       // but stretches vertically
                                        // size: new go.Size(160, 80),
                                        // column: 2,

                                        // width: 180,
                                        // stretch: go.GraphObject.Fill,
                                        // background: 'white',
                                        // defaultAlignment: go.Spot.Left,
                                        // defaultColumnSeparatorStroke: 'lightgrey',
                                        // defaultColumnSeparatorStrokeWidth: 0.5,
                                        // defaultRowSeparatorStroke: 'lightgrey',
                                        // defaultRowSeparatorStrokeWidth: 0.5,
                                    },

                                    Make(go.RowColumnDefinition,
                                        { column: 0, width: 100 }
                                    ),
                                    Make(go.RowColumnDefinition,
                                        { column: 1, width: 65 }
                                    ),
                                    Make(go.RowColumnDefinition,
                                        { column: 2, width: 15 }
                                    ),

                                    new go.Binding('TABLE.itemArray', 'properties'),
                                    // new go.Binding('TABLE.column', '', () => 0),
                                    {
                                        'TABLE.itemTemplate':
                                            Make(go.Panel, go.Panel.TableRow,
                                                {
                                                    row: 1,
                                                    defaultStretch: go.GraphObject.Horizontal,
                                                    // fromSpot: go.Spot.LeftRightSides,
                                                    // toSpot: go.Spot.LeftRightSides,
                                                    // fromLinkable: true,
                                                    // toLinkable: true
                                                    // height: 20,
                                                    name: 'fieldTableRow',
                                                    background: 'transparent',
                                                    // click: (e: go.InputEvent, obj: go.Panel) => onFieldClicked && onFieldClicked(e, obj)
                                                },
                                                new go.Binding(),

                                                Make(go.Panel, 'Auto',
                                                    {
                                                        column: 0,
                                                        // height: 20,
                                                        toolTip: NodeTemplates.createTextBlockTooltip('FieldName', 'fieldNameTextBlock')
                                                    },
                                                    Make(go.TextBlock,
                                                        {
                                                            name: 'fieldNameTextBlock',
                                                            font: '6pt sans-serif',
                                                            margin: new go.Margin(5, 3, 3, 10),
                                                            overflow: go.TextBlock.OverflowEllipsis,
                                                            maxLines: 1,
                                                            width: 100
                                                        },
                                                        new go.Binding('text', 'FieldName')
                                                    )
                                                ),

                                                Make(go.Panel, 'Auto', { column: 1 },
                                                    Make(go.TextBlock,
                                                        {
                                                            name: 'fieldTypeTextBlock',
                                                            font: '6pt sans-serif',
                                                            margin: new go.Margin(5, 3, 3, 10),
                                                            overflow: go.TextBlock.OverflowEllipsis,
                                                            maxLines: 1,
                                                            width: 60
                                                        },
                                                        new go.Binding('text', 'DataType', (dataType: DataType) => DataType[dataType])
                                                    )
                                                ),
                                            ),

                                        'TABLE.background': 'white',
                                        'TABLE.defaultAlignment': go.Spot.Left,
                                        'TABLE.defaultColumnSeparatorStroke': 'lightgrey',
                                        'TABLE.defaultColumnSeparatorStrokeWidth': 0.5,
                                        'TABLE.defaultRowSeparatorStroke': 'lightgrey',
                                        'TABLE.defaultRowSeparatorStrokeWidth': 0.5,

                                        // 'TABLE.width': 180,
                                        // 'TABLE.columnSpan': 3,
                                    }
                                )
                            )
                        )
                    )
                )
            )
        ) as go.Node;
    }

Try removing the Auto Panel that is around the “ScrollingTable” panel.

Generally you should not have an Auto Panel without two or more elements.

Thanks for the reply Walter.

I have got it to work by removing the panel as well as the column definitions inside the scrolling table.

It’s not perfectly lined up though, do you have an idea on how I can do that without the column definitions?

One more question I have is about the scroll behaviour. Is there any way to get the scrolling to stop at the last row item?

Basically I want it so that the OptimisticLockID field will be at the bottom of the table, and that further scrolling cannot happen, so that there can’t be a big gap between the last field and the bottom of the node

Do you want your “DATA TYPE” column header to span the last two columns by setting its GraphObject.columnSpan to 2?

For the second question, you’ll need to modify the incrTableIndex and updateScrollBar functions to use a lower maximum value for Panel.topIndex than it currently does.

I was trying to create a small 3rd column in the header to accommodate for the scroll bar, but if it is easier to get it lined up with just the columnSpan then I can adjust accordingly.

Alright, I will have a look at those two functions.

Will let you know how it works out.

I’ve added the columnSpan but it didn’t seem to change anything in the layout.

image

I got the scrolling to the bottom to work. Thanks for pointing me in the right direction.

Don’t you want just two columns? If so, don’t declare that there is a third column and make sure there’s nothing in any other column besides the first two, for the two header objects.

Have the “ScrollingTable” Panel, which is in the second row of the main Table Panel, use its normal column definitions (one for content and one for the optional scrollbar) and have it span both columns of the main Table.

Node, "Auto",
    Shape, "RoundedRectangle",  // border
    Panel, "Table",
        ... header ... row: 0,
        Panel, "Table", row: 1,
            RCD, column: 0, width: 100,
            RCD, column: 1, width: 80,
            TextBlock, "FIELD NAME", row: 0, column: 0,
            TextBlock, "DATA TYPE", row: 0, column: 1,
            Panel, "ScrollingTable", row: 1, column: 0, columnSpan: 2,
                . . .
        ... footer ... row: 2

Don’t need to use “TableRow” panels except as Panel.itemTemplate.

Okay that makes sense. I have made the changes and it is looking better, but still not lining up exactly.
When using a a few fixed widths I have managed to get it more or less in line, but not exactly perfect.

This is my current node template code:

public static createViewNodeTemplate(
        onClicked: (e: go.InputEvent, obj: go.Node) => void
    ): go.Node {

        return Make(go.Node, 'Auto',
            {
                name: 'entityNodeView',
                cursor: 'pointer',
                selectionAdorned: false,
                zOrder: 1,
                click: (e: go.InputEvent, obj: go.Node) => onClicked && onClicked(e, obj)
            },
            new go.Binding('location', 'location', go.Point.parse),
            Make(go.Shape, 'RoundedRectangle',
                {
                    name: 'entityShape',
                    stroke: Palette.unselectedColour,
                    strokeWidth: 0.5,
                    parameter1: 2,
                    fill: 'white',
                    width: 180
                },
            ),
            Make(go.Panel, go.Panel.Table,
                {
                    name: 'viewEntityMainTable',
                    width: 180,
                    defaultRowSeparatorStroke: 'grey',
                    defaultRowSeparatorStrokeWidth: 0.5,
                },

                Make(go.Panel, go.Panel.TableRow, { row: 0 },
                    // NodeTemplates.createHeaderTable(undefined, undefined, false)

                    Make(go.Panel, go.Panel.Table,
                        {
                            name: 'headerTable',
                            width: 180,
                            background: Palette.entityHeaderColour
                        },

                        Make(go.Panel, go.Panel.TableRow, { row: 0 },

                            Make(go.Panel, 'Auto',
                                {
                                    column: 0,
                                    toolTip: NodeTemplates.createTextBlockTooltip('objectName', 'entityHeaderText')
                                },
                                Make(go.TextBlock,
                                    {
                                        name: 'entityHeaderText',
                                        margin: new go.Margin(8, 2),
                                        alignment: go.Spot.Center,
                                        font: 'bold 7pt sans-serif',
                                        textAlign: 'center',
                                        stroke: Palette.entityTextColour,
                                        overflow: go.TextBlock.OverflowEllipsis,
                                        maxLines: 1,
                                        width: 160
                                    },
                                    new go.Binding('text', 'objectName')
                                )
                            )
                        )
                    )
                ),

                Make(go.Panel, go.Panel.TableRow, { row: 1 },

                    Make(go.Panel, go.Panel.Table,
                        {
                            defaultColumnSeparatorStroke: 'lightgray',
                            defaultColumnSeparatorStrokeWidth: 0.5,
                            defaultRowSeparatorStroke: 'lightgray',
                            defaultRowSeparatorStrokeWidth: 0.5
                        },

                        Make(go.RowColumnDefinition,
                            { column: 0, width: 100 }
                        ),
                        Make(go.RowColumnDefinition,
                            { column: 1, width: 80 }
                        ),
                        Make(go.RowColumnDefinition,
                            { row: 0, height: 20 }
                        ),

                        Make(go.TextBlock, 'FIELD NAME',
                            {
                                row: 0,
                                column: 0,
                                stroke: Palette.entityTextColour,
                                margin: new go.Margin(3),
                                textAlign: 'center',
                                verticalAlignment: go.Spot.Center,
                                font: 'bold 6pt sans-serif'
                            }
                        ),
                        Make(go.TextBlock, 'DATA TYPE',
                            {
                                row: 0,
                                column: 1,
                                stroke: Palette.entityTextColour,
                                margin: new go.Margin(3),
                                textAlign: 'center',
                                verticalAlignment: go.Spot.Center,
                                font: 'bold 6pt sans-serif'
                            }
                        ),

                        // NodeTemplates.createFieldTable()

                        Make('ScrollingTable', 'TABLE',
                            {
                                // Create binding to determine the max/desired size, up until 10 items in the field table
                                // Eg:
                                // row = 20, rowCount = 5, totalHeight = 100
                                // row = 20, rowCount = 10, totalHeight = 200
                                // row = 20, rowCount = 15, totalHeight = 200
                                desiredSize: new go.Size(NaN, 100),
                                stretch: go.GraphObject.Fill,
                                row: 1,
                                column: 0,
                                columnSpan: 2,
                                width: 180,
                                'TABLE.background': 'white',
                                'TABLE.defaultAlignment': go.Spot.Left,
                                'TABLE.defaultColumnSeparatorStroke': 'lightgrey',
                                'TABLE.defaultColumnSeparatorStrokeWidth': 0.5,
                                'TABLE.defaultRowSeparatorStroke': 'lightgrey',
                                'TABLE.defaultRowSeparatorStrokeWidth': 0.5,
                            },

                            Make(go.RowColumnDefinition,
                                { column: 0, width: 166 }
                            ),

                            new go.Binding('TABLE.itemArray', 'properties'),
                            {
                                'TABLE.itemTemplate':
                                    Make(go.Panel, go.Panel.TableRow,
                                        {
                                            row: 0,
                                            defaultStretch: go.GraphObject.Horizontal,
                                            name: 'fieldTableRow',
                                            background: 'transparent',
                                            height: 20,
                                            // click: (e: go.InputEvent, obj: go.Panel) => onFieldClicked && onFieldClicked(e, obj)
                                        },
                                        new go.Binding(),

                                        Make(go.Panel, 'Auto',
                                            {
                                                column: 0,
                                                height: 20,
                                                width: 100,
                                                toolTip: NodeTemplates.createTextBlockTooltip('FieldName', 'fieldNameTextBlock')
                                            },
                                            Make(go.TextBlock,
                                                {
                                                    name: 'fieldNameTextBlock',
                                                    font: '6pt sans-serif',
                                                    margin: new go.Margin(5, 3, 3, 10),
                                                    overflow: go.TextBlock.OverflowEllipsis,
                                                    maxLines: 1,
                                                    width: 100
                                                },
                                                new go.Binding('text', 'FieldName')
                                            )
                                        ),

                                        Make(go.Panel, 'Auto', { column: 1 },
                                            Make(go.TextBlock,
                                                {
                                                    name: 'fieldTypeTextBlock',
                                                    font: '6pt sans-serif',
                                                    margin: new go.Margin(5, 3, 3, 10),
                                                    overflow: go.TextBlock.OverflowEllipsis,
                                                    maxLines: 1,
                                                    width: 60
                                                },
                                                new go.Binding('text', 'DataType', (dataType: DataType) => DataType[dataType])
                                            )
                                        ),
                                    )
                            }
                        )
                    )
                )
            )
        ) as go.Node;
    }

Result:

Little bit off: