RowColumnDefinition and chaining syntax

How does one use / specify a RowColumnDefinition when using method chaining instead of $ make.
I can’t figure out to do what i assume is a very basic thing:
I want to have a table with 3 columns and an unspecified number of rows.
These rows will be made using new go.Panel(‘TableRow’)

All 3 columns have a specific width, some rows may have 0 elements in a column, and i still want them to align properly. Each row should also have the same height.

export const diagramDataTableComponentTemplate = new go.Node('Table', {
    width: 190
})
    .add(new go.Panel('TableRow', { row:0})
        .add(new go.Shape('Rectangle', {
            column: 0,
            fill: '#FF0000',
            strokeWidth: 0,
            width: 30,
            height: 30,
        }))
        .add(new go.Shape('Rectangle', {
            column: 2,
            fill: '#0000ff',
            strokeWidth: 0,
            height: 30,
            width:30,
        })))
    .add(new go.Panel('TableRow', {row: 1})
        .add(new go.Shape('Rectangle', {
            column: 0,
            fill: '#0FF000',
            strokeWidth: 0,
            width: 30,
            height: 30,
        }))
        .add(new go.Shape('Rectangle', {
            column: 1,
            fill: '#F00FFF',
            strokeWidth: 0,
            width: 150,
            height: 30,
        })))
    .add(new go.Panel('TableRow', {row: 2})
        .add(new go.Shape('Rectangle', {
            column: 1,
            fill: '#00FFF0',
            strokeWidth: 0,
            width: 150,
            height: 30,
        })))

I do not want to specify the height in each of these child elements, i just want to specify on the Table node once : ‘My column widths are [30, 150, 30], my row heights are 30’. If none of the rows have a left or right column value, that column should still take up its 30px despite being empty.

Screenshot 2023-02-20 at 15.57.27
Screenshot 2023-02-20 at 16.06.20

It sounds like a good fit for ItemArrays, depending on your requirements.

Your node template could actually be quite small, just this:

        myDiagram.nodeTemplate = new go.Node('Table', {
          width: 210,
          itemTemplate: rowTemplate,
        }).bind('itemArray', 'rows');

With almost all the complexity in your itemTemplate, which would be a TableRow, plus three primary panels that contain the content for each cell.

Here’s an example: https://codepen.io/simonsarris/pen/GRXomNP?editors=1010

In my example you actually have a Table node, with tableRows, and each tableRow contains 3 more tables, but this is just to center the single textblock easily. It could be done a number of ways depending on the complexity of your end node.

Note also how I made makeTextBlock for repetitive code in the 3 textblocks required. This could be expanded for each cell.

If this is closer to what you want but not quite there, or if your end goal is significantly more complex than the pictures you’ve shared so far, let me know.

Hi Simon,

Thanks for the reply. I’m aware of ItemArrays. One thing i forgot to mention is that the table is not entirely dynamic.

Basically it’s something like

  • Table static section -
  • some dynamic rows -
  • another static section -

I didn’t figure out how to

  • Add static sections to a table and then have control over where the itemArray items will be placed in relation to these sections.
  • Also, how to have have multiple sections of itemArrays, so i thought i needed to add multiple tables in just a vertical panel, but then these tables all need to have the same width for each column etc so that became similar code copy-pasted…

Hope this is a bit clear. So that’s why i was thinking 'can’t i just globally define the column widths on a table node instead of each time in these static and dynamic sections

Do something like:

new go.Binding("itemArray", "???", a => Static1.concat(a, Static2))

Where Static1 and Static2 are consts holding your unchanging Arrays of Objects.

I figured i re-use this topic instead of creating a new one.

Can you please give me the most basic example on how to make a fixed-dimension table layout.
The bottom section of GoJS Table Panels -- Northwoods Software doesn’t provide enough info and it is all i can find about it.

const createTableRow = (rowIndex) => {
    const tableRow = new go.Panel('TableRow', {height: 30, row: rowIndex})
    tableRow.addRowColumnDefinition(new go.RowColumnDefinition({column:0, width:15,background: '#ff0000'}))
    tableRow.addRowColumnDefinition(new go.RowColumnDefinition({column:1, width:150, background: '#00ff00'}))
    tableRow.addRowColumnDefinition(new go.RowColumnDefinition({column:2, width:15, background: '#0000ff'}))
    return tableRow
}

export const listTemplate = new go.Node('Table', {stretch: go.GraphObject.Fill})
    .add(createTableRow(0))
    .add(createTableRow(1).add(new go.TextBlock('hi',{column:1})))

Expected node: two table rows with 3 columns each with dimensions 30x15, 30x150, 30x15 and their corresponding background. These cells should ALWAYS respect these dimensions, even when empty. e.g. adding a rectangle to a row / column should restrict the rectangle to its cell size etc, same with text.

Actual node: just the text ‘hi’… It feels like height on Tablerow and width on RowColumnDefinion have absolutely 0 impact. I’ve tried other stuff and permutations using combination of minSize, stretch, … none seem to do anything… I’ve spent way too long on this already what seems to me like super basic usage. I just can’t find a similar example.

Thanks in advance

Note that RowColumnDefinitions are added to the Table itself, not a TableRow or TableColumn

Do you the table to always be 3 column and 2 rows? Or is there more dynamically expected of it than that?

If that’s all there will ever be, you do not need to use TableRows or TableColumns, you can just add the RowColumnDefinitions, something like this:

      myDiagram.nodeTemplate = new go.Node('Table')
        .addRowColumnDefinition(new go.RowColumnDefinition({ column: 0, width: 15, background: 'rgba(255,0,0,.3)' }))
        .addRowColumnDefinition(new go.RowColumnDefinition({ column: 1, width: 150, background: 'rgba(55,255,0,.3)' }))
        .addRowColumnDefinition(new go.RowColumnDefinition({ column: 2, width: 15, background: 'rgba(0,0,255,.3)' }))

        .addRowColumnDefinition(new go.RowColumnDefinition({ row: 0, height: 30 }))
        .addRowColumnDefinition(new go.RowColumnDefinition({ row: 1, height: 30, background: 'rgba(0,0,255,.3)' }))

The background colors are just to visualize the space taken up. In this example I added a few textblocks also: https://codepen.io/simonsarris/pen/PodmBGm?editors=1010

Is that what you’re expecting? Or are there other constraints?

Hi Simon,

The table will always be 3 columns, the number of rows varies depending on the type of node.
I wanted to obtain a consistent look between all these table-based node types. Hence i wanted to create a a nice abstraction ‘create row’.

const createTableRow = (rowIndex) => {
    const tableRow = new go.Panel('TableRow', {height: 30, row: rowIndex})
    return tableRow
}

const component = new go.Panel('Table', {stretch: go.GraphObject.Fill})
    .add(createTableRow(0))
    .add(createTableRow(1).add(new go.TextBlock('hi',{column:1})))
    .addRowColumnDefinition(new go.RowColumnDefinition({column:0, width:15,background: '#ff0000'}))
    .addRowColumnDefinition(new go.RowColumnDefinition({column:1, width:150, background: '#00ff00'}))
    .addRowColumnDefinition(new go.RowColumnDefinition({column:2, width:15, background: '#0000ff'}))

So i updated the code, now i see the row as expected but only for the row with actual content. how do i make a table respect the ‘height: 30’ of a table row, even when empty?

The rowColumnDefinition syntax is still a bit weird to me. I would expect it to be able to say stuff like ‘any row in this table should be of height 30’. But RowColumnDefinition always expect a row (or column). So how can i say ‘any row’?

I would either expect a feature to exist to say row: ‘any’, or just allow a RowColumnDefinition to specify a height on a column instead of API saying about height: ‘This describes the row height if isRow is true; otherwise this property is meaningless. The value must be non-negative and finite.’
I would expect this definition:

 .addRowColumnDefinition(new go.RowColumnDefinition({column:0, width:15, height:30, background: '#ff0000'}))

To mean ‘any cell in column 0 of this table has a height of 30’ so i don’t understand the design choice why it is ignored for !isRow. or if the naming is too confusing as it might be interpreted as ‘entire column height’, give it the name cellHeight.

TableRows and TableColumns are best thought of as containers for other GraphObjects, that automatically assign values for those objects (mostly row and column properties). Their primary advantage is that you can use them in itemTemplates to dynamically add a variable number of rows or columns to a table depending on the model data for each Node. It’s difficult to know if they’ll be helpful for you unless you can give a bit more data your data model. If your Table dimensions are truly fixed in the node template creation stage, they may not be worth using at all.

But regardless, TableRows/Columns themselves do not take up any space, so you’ll still need a RowColumnDefinition for that forced sizing when the row is empty.

RowColumnDefinitions can only act as either one or the other, defining rules for a row or for a column, they cannot give instructions for both a row and a column, so if it is set to “column”, it can only act upon the width, and not the height.

I can’t figure out how to send you a private message.
if you send me an email (that this account uses), I can share some screens on what i want to achieve that i’d rather not share publicly.

Yes, feel free to send mail to gojs (at) nwoods.com.