Merged or Nested column headers in an editable grid

Has anyone figured out a good way to emulate nested/merged column headers in an editable grid?  I have attached an image to show what I mean.

As far as I know, there is no OOTB way to do this, but it must be a relatively common requirement.  Any suggestions would be greatly appreciated!

  Discussion posts and replies are publicly visible

Parents
  • You are correct there is no way to achieve this within the standard grid components OOTB.  However, you can create a custom grid by combining other components, such as below.

    a!localVariables(
      local!data: {
        {id: 1, text1: null, text2: null, text3: null, text4: null, text5: null, text6: null, text7: null, text8: null},
        {id: 2, text1: null, text2: null, text3: null, text4: null, text5: null, text6: null, text7: null, text8: null},
        {id: 3, text1: null, text2: null, text3: null, text4: null, text5: null, text6: null, text7: null, text8: null}
      },
      {
        a!columnsLayout(
          marginBelow: "NONE",
          spacing: "NONE",
          columns: {
            a!columnLayout(
              contents: {
                a!cardLayout(
                  style: "INFO",
                  contents: {
                    a!richTextDisplayField(
                      align: "CENTER",
                      labelPosition: "COLLAPSED",
                      value: a!richTextItem(
                        text: "Header 1",
                        style: "STRONG"
                      )
                    )
                  }
                )
              }
            ),
            a!columnLayout(
              contents: {
                a!cardLayout(
                  style: "INFO",
                  contents: {
                    a!richTextDisplayField(
                      align: "CENTER",
                      labelPosition: "COLLAPSED",
                      value: a!richTextItem(
                        text: "Header 2",
                        style: "STRONG"
                      )
                    )
                  }
                )
              }
            )
          }
        ),
        a!columnsLayout(
          marginBelow: "NONE",
          spacing: "NONE",
          columns: {
            a!columnLayout(
              contents: {
                a!cardLayout(
                  style: "WARN",
                  contents: {
                    a!richTextDisplayField(
                      align: "CENTER",
                      labelPosition: "COLLAPSED",
                      value: a!richTextItem(
                        text: "Sub Header A",
                        style: "STRONG"
                      )
                    )
                  }
                )
              }
            ),
            a!columnLayout(
              contents: {
                a!cardLayout(
                  style: "WARN",
                  contents: {
                    a!richTextDisplayField(
                      align: "CENTER",
                      labelPosition: "COLLAPSED",
                      value: a!richTextItem(
                        text: "Sub Header B",
                        style: "STRONG"
                      )
                    )
                  }
                )
              }
            ),
            a!columnLayout(
              contents: {
                a!cardLayout(
                  style: "WARN",
                  contents: {
                    a!richTextDisplayField(
                      align: "CENTER",
                      labelPosition: "COLLAPSED",
                      value: a!richTextItem(
                        text: "Sub Header C",
                        style: "STRONG"
                      )
                    )
                  }
                )
              }
            ),
            a!columnLayout(
              contents: {
                a!cardLayout(
                  style: "WARN",
                  contents: {
                    a!richTextDisplayField(
                      align: "CENTER",
                      labelPosition: "COLLAPSED",
                      value: a!richTextItem(
                        text: "Sub Header D",
                        style: "STRONG"
                      )
                    )
                  }
                )
              }
            ),
          }
        ),    
        a!forEach(
          items: local!data,
          expression: 
          a!columnsLayout(
            marginBelow: "NONE",
            spacing: "NONE",
            columns: {
              a!columnLayout(
                contents: {
                  a!textField(
                    labelPosition: "COLLAPSED",
                    value: fv!item.text1,
                    saveInto: local!data[fv!index].text1
                  )
                }
              ),
              a!columnLayout(
                contents: {
                  a!textField(
                    labelPosition: "COLLAPSED",
                    value: fv!item.text2,
                    saveInto: local!data[fv!index].text2
                  )
                }
              ),
              a!columnLayout(
                contents: {
                  a!textField(
                    labelPosition: "COLLAPSED",
                    value: fv!item.text3,
                    saveInto: local!data[fv!index].text3
                  )
                }
              ),
              a!columnLayout(
                contents: {
                  a!textField(
                    labelPosition: "COLLAPSED",
                    value: fv!item.text4,
                    saveInto: local!data[fv!index].text4
                  )
                }
              ),
              a!columnLayout(
                contents: {
                  a!textField(
                    labelPosition: "COLLAPSED",
                    value: fv!item.text5,
                    saveInto: local!data[fv!index].text5
                  )
                }
              ),
              a!columnLayout(
                contents: {
                  a!textField(
                    labelPosition: "COLLAPSED",
                    value: fv!item.text6,
                    saveInto: local!data[fv!index].text6
                  )
                }
              ),
              a!columnLayout(
                contents: {
                  a!textField(
                    labelPosition: "COLLAPSED",
                    value: fv!item.text7,
                    saveInto: local!data[fv!index].text7
                  )
                }
              ),
              a!columnLayout(
                contents: {
                  a!textField(
                    labelPosition: "COLLAPSED",
                    value: fv!item.text8,
                    saveInto: local!data[fv!index].text8
                  )
                }
              )
            }
          )
        ),
        a!richTextDisplayField(
          labelPosition: "COLLAPSED",
          value: {
            a!richTextIcon(
              icon: "plus",
              color: "ACCENT"
            ),
            a!richTextItem(
              text: "Add a Row",
              link: a!dynamicLink(
                label: "Add a Row",
                value: {id: count(local!data)+1, text1: null, text2: null, text3: null, text4: null, text5: null, text6: null, text7: null, text8: null},
                saveInto: {
                  a!save(
                    local!data,
                    append(
                      local!data,
                      save!value
                    )
                  )
                }
              )
            )
          }
        )
      }
    ),
    

  • Thank you for the suggestion!  I am a bit worried about performance because the grid will have many rows.  Do you know of any way that I could use a normal editable grid, but somehow line up a card above a specific number of the columns?  Or another elegant way to denote that columns are grouped?

Reply Children