Skip to main content
allenp0001
Known Participant
July 3, 2023
Solved

Expand/Collapse Rows within an Expanded/Collapse Row

  • July 3, 2023
  • 10 replies
  • 1 view

Has any one done an expanded/collapse row grid within an expanded/collapse row grid.  I am looking at the https://docs.appian.com/suite/help/23.2/recipe-expand-collapse-rows-in-a-tree-grid.html#expression

in the documentation and it look like what I am looking for, I just need a third level.  I am looking at creating a grid that displays primary customers, then expands to show those primary customers ship to's then another expansion to show the ship to's contacts.

Best answer by mikes0011

Well for the sake of argument I've whipped you up a quick example using a probably-oversimplified local data structure, but which might at least help you solidify the necessary "skeleton" of the thing you're trying to build...

a!localVariables(
  
  local!nestedDataSet: {
    a!map(
      name: "Set 1",
      contents: {
        a!map(
          itemName: "item a1",
          features: {
            a!map(featureName: "feature q1", widgetCount: tointeger(rand()*20)),
            a!map(featureName: "feature q2", widgetCount: tointeger(rand()*20)),
            a!map(featureName: "feature q3", widgetCount: tointeger(rand()*20)),
          }
        ),
        a!map(
          itemName: "item a2",
          features: {
            a!map(featureName: "feature w1", widgetCount: tointeger(rand()*20)),
            a!map(featureName: "feature w2", widgetCount: tointeger(rand()*20)),
            a!map(featureName: "feature w3", widgetCount: tointeger(rand()*20)),
          }
        ),
        a!map(
          itemName: "item a3",
          features: {
            a!map(featureName: "feature e1", widgetCount: tointeger(rand()*20)),
            a!map(featureName: "feature e2", widgetCount: tointeger(rand()*20)),
            a!map(featureName: "feature e3", widgetCount: tointeger(rand()*20)),
          }
        )
      }
    ),
    a!map(
      name: "Set 2",
      contents: {
        a!map(
          itemName: "item b1",
          features: {
            a!map(featureName: "feature r1", widgetCount: tointeger(rand()*20)),
            a!map(featureName: "feature r2", widgetCount: tointeger(rand()*20)),
            a!map(featureName: "feature r3", widgetCount: tointeger(rand()*20)),
          }
        ),
        a!map(
          itemName: "item b2",
          features: {
            a!map(featureName: "feature t1", widgetCount: tointeger(rand()*20)),
            a!map(featureName: "feature t2", widgetCount: tointeger(rand()*20)),
            a!map(featureName: "feature t3", widgetCount: tointeger(rand()*20)),
          }
        ),
        a!map(
          itemName: "item b3",
          features: {
            a!map(featureName: "feature y1", widgetCount: tointeger(rand()*20)),
            a!map(featureName: "feature y2", widgetCount: tointeger(rand()*20)),
            a!map(featureName: "feature y3", widgetCount: tointeger(rand()*20)),
          }
        )
      }
    ),
  },
  
  a!sectionLayout(
    
    contents: {
      a!gridLayout(
        headerCells: {
          a!gridLayoutHeaderCell(label: "Name"),
          a!gridLayoutHeaderCell(label: "Quantity")
        },
        
        rows: a!forEach(
          local!nestedDataSet,
          
          a!localVariables(
            local!currentLevel1: fv!item,
            local!isCurrentLevelExpanded: false(),
            
            {
              a!gridRowLayout(
                contents: {
                  a!richTextDisplayField(
                    value: a!richTextItem(
                      text: fv!item.name,
                      link: a!dynamicLink(
                        saveInto: a!save(local!isCurrentLevelExpanded, not(local!isCurrentLevelExpanded))
                      ),
                      linkStyle: "STANDALONE"
                    )
                  ),
                  a!richTextDisplayField(value: "Items: " & length(fv!item.contents))
                }
              ),
              
              if(
                local!isCurrentLevelExpanded,
                
                a!forEach(
                  local!currentLevel1.contents,
                  a!localVariables(
                    local!currentLevel2: fv!item,
                    local!isCurrentChildLevelExpanded: false(),
                    {
                      a!gridRowLayout(
                        contents: {
                          a!richTextDisplayField(
                            value: {
                              " -  ",
                              a!richTextItem(
                                text: fv!item.itemName,
                                link: a!dynamicLink(
                                  saveInto: a!save(local!isCurrentChildLevelExpanded, not(local!isCurrentChildLevelExpanded))
                                )
                              )
                            }
                          ),
                          a!richTextDisplayField(
                            value: a!richTextItem(
                              text: "  Features: " & length(fv!item.features),
                              style: "EMPHASIS"
                            )
                          )
                        }
                      ),
                      
                      if(
                        local!isCurrentChildLevelExpanded,
                        a!forEach(
                          local!currentLevel2.features,
                          a!gridRowLayout(
                            contents: {
                              a!richTextDisplayField(
                                value: {
                                  " - -  ",
                                  a!richTextItem(
                                    text: fv!item.featureName,
                                    size: "SMALL"
                                  )
                                }
                              ),
                              a!richTextDisplayField(
                                value: a!richTextItem(
                                  text: "    Widget Count: " & fv!item.widgetCount,
                                  size: "SMALL"
                                )
                              )
                            }
                          )
                        ),
                        {}
                      )
                    }
                  )
                ),
                {}
              )
            }
          )
        )
      )
    }
  )
)

10 replies

mikes0011
Brainy
July 3, 2023

It should be achievable following the same sort of logic as in that recipe - i don't asusme there are any pre-set recipes offering an additional level of expansion, so my best guess is you'll probably need to work out that logic on your own (though if you're lucky, maybe someone here already has and can post some example code - i haven't).

One suggestion I could offer here is to write a specialized rule / sub-interface specifically to handle each parent-level grid row (where each iteration would return 1 set if it's non-expanded, and additional sets if it has been expanded), as this sort of encapsulation might make it a little easier to work with in the context of your parent interface.  Though I believe it's not a requirement, so you can probably accomplish this using whichever style ends up being easiest for you to work with.

The Expression Guru
allenp0001
Known Participant
July 5, 2023

Thanks Mike, I love the suggestion, I had not thought about doing that.

I am working on working out the logic of the recipe to add my third layer.

stefanhelzle0001
Brainy
July 5, 2023

You could turn this into a reusable and customizable component. Find some inspiration here

https://appian.rocks/2022/09/19/building-customisable-components/

https://appian.rocks/2022/10/03/building-a-collapsible-tree/