foreach incrementation

{a!localVariables(
local!item:0,
a!forEach(
items: enumerate(2),
expression: a!columnsLayout(
columns: a!localVariables(
local!outerIndex: fv!item,
local!item:1,
a!forEach(
items: 1+enumerate(3),
expression: a!columnLayout(
contents: a!cardLayout(
style: "INFO",
contents: {
a!textField(
value:local!item,
saveInto:a!save(local!item,tointeger(local!item)+1),
),
a!richTextDisplayField(
labelPosition: "COLLAPSED",
align: "CENTER",
value: a!richTextItem(
text:local!item,
color: "#1a1a00",
size: "MEDIUM",
),
),
},
height: "MEDIUM",
shape: "ROUNDED",
),

)
)
)
)
),
)
}

The above code will have 2 columns and 3 rows.

it is giving the below output.

but i want to display 1 2 3

                                  4 5 6.

If i apply some logic , i will get 1 2 3

                                                 3 4 5

incrementing variable also not possible here. kindly help.

  Discussion posts and replies are publicly visible

  • Thanks Stefan, for always a great guide. Actually this code was from Nandinip and most logic was about logic ( Use case was based on two integers Let say 2 & 3) Need to draw dynamic texboxes  in sequence with in a way that it should be of 3 columns and 2 rows.

  • 0
    Certified Lead Developer
    in reply to nandhinip

    You're doing a lot of repeated / hardcoded calculations on things like column positioning, causing the code to get too complicated to read pretty quickly as we can see here.  Meanwhile you're not properly calculating the proper column position for each data cell in a programmatic way, which is tripping up what you're trying to do.

    The suggestion I always make with this is to let your local variables do some of the heavy lifting, then simply iterate.  First, we set a local variable to the number of total columns (to prevent it from being hardcoded everywhere and thus incomprehensible).  Then we step over the original data array and create a new array containing the initial data plus a new element indicating its column position, using the MOD() operator over the item's index and the number of columns.

    This forms a secondary local variable array matching the first one, but with elements like this:

    Then instead of doing so much stressful redundant calculation inside the columns / cards, we can just rely on the column number stored in the current local variable position.

    And then when it's time to print out the actual values, we can get rid of some of the mess:

    In this way you can have a dynamic display of tiles in columns, whether it's 2 columns,

    ...or 3 columns,

    ...or 7 columns...
     ... and so-on.

    a!localVariables(
      local!selectedColumn:0,
      local!createdcard:0,
      local!datas: {
        {Name: "Name1", Description: "Description1"},
        {Name: "Name2", Description: "Description2"},
        {Name: "Name3", Description: "Description3"},
        {Name: "Name4", Description: "Description4"},
        {Name: "Name5", Description: "Description5"},
        {Name: "Name6", Description: "Description6"},
        {Name: "Name7", Description: "Description7"},
        {Name: "Name8", Description: "Description8"},
        {Name: "Name9", Description: "Description9"},
        {Name: "Name10", Description: "Description10"},
        {Name: "Name11", Description: "Description11"},
        {Name: "Name12", Description: "Description12"},
        {Name: "Name13", Description: "Description13"},
        {Name: "Name14", Description: "Description14"},
        {Name: "Name15", Description: "Description15"},
      },
      local!selectedCard,
      
      
      local!numColumns: 4,
      
      local!columnPositions: a!forEach(
        local!datas,
        a!localVariables(
          local!modulo: mod(fv!index, local!numColumns),
          a!map(
            data: fv!item,
            column: if(local!modulo = 0, local!numColumns, local!modulo)
          )
        )
      ),
      
      {
        a!richTextDisplayField(
          labelPosition: "COLLAPSED",
          value: {
            a!richTextItem(
              text: "Data",
              color: "#b366ff",
              size: "LARGE"
            ),
          },
          showWhen: isNull(local!selectedCard),
          align: "CENTER"
        ),  
    
        {
          a!columnsLayout(
            marginBelow: "NONE",
            spacing: "SPARSE",
            columns: {
              a!forEach(
                items: 1 + enumerate(local!numColumns),
                expression: {
                  a!localVariables(
                    local!columnIndex: fv!index,
                    
                    a!columnLayout(
                      contents: {
                        a!forEach(
                          /*items: 1+enumerate(count(local!datas.Name)),*/
                          items: local!columnPositions,
                          expression: if(
                            fv!item.column <> local!columnIndex,
                            {},
                            
                            {
                              a!cardLayout(
                                style: "INFO",
                                marginBelow: "STANDARD",
                                contents: {                                    
                                  a!richTextDisplayField(
                                    labelPosition: "COLLAPSED",
                                    value: {
                                      char(10),
                                      char(10),
                                      a!richTextItem(
                                        /*text:if(((fv!index+(local!columnIndex-1)*2)>count(local!datas.Name))," ",local!datas[fv!index+(local!columnIndex-1)*2].Name),*/
                                        text: fv!item.data.Name,
                                        color: "#1a1a00",
                                        size: "MEDIUM"
                                      ),
                                      char(10),
                                      char(10),
                                      a!richTextItem(
                                        /*text: if(((fv!index+(local!columnIndex-1)*2)>count(local!datas.Name))," ",local!datas[fv!index+(local!columnIndex-1)*2].Description),*/
                                        text: fv!item.data.Description,
                                        color: "#1a1a00",
                                        size: "SMALL",
                                        style: "PLAIN"
                                      ),
                                      char(10),
    
                                      a!richTextItem(
                                        text: " ",
                                        color: "#1a1a00",
                                        size: "SMALL",
                                        style: "PLAIN"
                                      )
    
                                    },
                                    align: "LEFT"
    
                                  ),
                                  a!richTextDisplayField(
                                    labelPosition: "COLLAPSED",                      
                                    value: a!richTextItem(                        
                                      text: {
                                        a!richTextIcon(
                                          icon: "external-link",
                                          altText: "external-link"
                                        ),
                                        " ",
                                        "viewmore ",
                                        fv!index
                                        /*&(fv!index+(local!columnIndex-1)*2),*/
                                      },
    
                                      link: a!dynamicLink(
                                        saveInto: {
                                          /*a!save(local!selectedCard, if(((fv!index+(local!columnIndex-1)*2)>count(local!datas.Name))," ",local!datas[fv!index+(local!columnIndex-1)*2].Name)),*/
                                          a!save(local!selectedCard, fv!index),
                                          /*a!save(local!selectedColumn, 1),*/
                                          a!save(
                                            local!createdcard,
                                            /*(fv!index+(local!columnIndex-1)*2)*/
                                            fv!item.data
                                          )
                                        }
                                      ),
                                      linkStyle: "STANDALONE",
                                      color:"#a64dff"
                                    ),
                                    align: "CENTER",
                                  ) 
                                },
                                height: "SHORT_PLUS",
                                shape: "ROUNDED",
                                /*showWhen: tointeger((fv!index+(local!columnIndex-1)*2))<=count(local!datas.Name),*/
                              ),
                              /*a!cardLayout(showBorder: false), */
                            }
                          )
    
                        ) 
                      },                          
                      width: "MEDIUM_PLUS"
                    )
                  )
                  /*a!columnLayout()*/
                }
              )
            },
            
            /*showWhen: isNull(local!selectedCard),*/
            showWhen: tointeger(local!selectedColumn = 0)
          )
        }
      }
    )

  • yes, As a beginner,has confusions to understand the behaviour of local variables and the scope. Thanks for the clear response.

  • +1
    Certified Lead Developer
    in reply to nandhinip

    I agree, getting used to the way local variables works in Appian (including scoping) takes some getting used to, as it doesn't behave the same way as it typically works in other programming languages, in a few important aspects.  But when you get used to how it DOES work, especially when you understand what i call "update chaining", it gets REALLY powerful.  Generally I suggest starting with smaller, simpler examples and gradually stepping up the complexity when you really understand what you currently have.

    BTW if you found my above code snippet useful, I would appreciate a "verify answer" and/or upvote when convenient for you.