DynamicLink and GridField

Hello:

I have the following code and the 'assessment score' (which, for now, is a value generated by a rand() function) changes value when I click on the 'Show details' icon.  Is there a way to prevent that from happening?

Thanks!

a!localVariables(
  /* We load the employee data into this variable. If you are populating
     this variable with a query, you would put .data at the end before passing
     it to the grid. */
  local!employees: {
    a!map(
      id: 11,
      name: "Elizabeth Ward",
      role: "Senior Engineer",
      team: "Front-End Components",
      pto: 15,
      startDate: today() - 500
    ),
    a!map(
      id: 22,
      name: "Michael Johnson",
      role: "Payroll Manager",
      team: "Accounts Payable",
      pto: 2,
      startDate: today() - 100
    ),
    a!map(
      id: 33,
      name: "John Smith",
      role: "Quality Engineer",
      team: "User Acceptance Testing",
      pto: 5,
      startDate: today() - 1000
    ),
    a!map(
      id: 44,
      name: "Diana Hellstrom",
      role: "UX Designer",
      team: "User Experience",
      pto: 49,
      startDate: today() - 1200
    ),
    a!map(
      id: 55,
      name: "Francois Morin",
      role: "Account Executive",
      team: "Commercial North America",
      pto: 15,
      startDate: today() - 700
    ),
    a!map(
      id: 66,
      name: "Maya Kapoor",
      role: "Regional Director",
      team: "Front-End Components",
      pto: 15,
      startDate: today() - 1400
    ),
    a!map(
      id: 77,
      name: "Anthony Wu",
      role: "Benefits Coordinator",
      team: "Accounts Payable",
      pto: 2,
      startDate: today() - 300
    ),
    
  },
  /* local!teamList would normally come from a constant or data source. */
  local!teamList: {
    "Accounts Payable",
    "User Acceptance Testing",
    "User Experience",
    "Commercial North America",
    "Front-End Components"
  },
  /* This variable is for storing the grid's selection. */
  local!selection,
  /* This variable is used to for the full row of data on the selected item
     to be passed to the details section of the interface. */
  local!selectedEmployee,
  local!readOnly: true,
  {
    a!columnsLayout(
      columns: {
        a!columnLayout(
          contents: {
            a!sectionLayout(
              label: "Employees",
              contents: {
                a!gridField(
                  data: local!employees,
                  columns: {
                    a!gridColumn(label: "Name", value: fv!row.name),
                    a!gridColumn(
                      label: "Assessment Score",
                      value: a!richTextDisplayField(
                        value: if(
                          rand(1) < 0.5,
                          a!richTextIcon(icon: "thumbs-up", color: "POSITIVE"),
                          a!richTextIcon(icon: "thumbs-down", color: "NEGATIVE")
                        )
                      ),
                      align: "CENTER"
                    ),
                    a!gridColumn(
                      align: "CENTER",
                      label: "Show Details",
                      value: a!richTextDisplayField(
                        value: a!richTextIcon(
                          icon: "search-plus",
                          link: a!dynamicLink(
                            value: fv!row,
                            saveInto: {local!selectedEmployee,local!selection}
                            
                          ),
                          linkStyle: "STANDALONE"
                        )
                      )
                    )
                  },
                  pageSize: 10,
                  shadeAlternateRows: false,
                  rowHeader: 1
                )
              }
            )
          }
        ),
        a!columnLayout(
          contents: {
            a!sectionLayout(
              label: "Details",
              contents: {
                a!richTextDisplayField(
                  value: a!richTextItem(
                    text: "No employee selected.",
                    color: "SECONDARY",
                    size: "MEDIUM",
                    style: "EMPHASIS"
                  ),
                  showWhen: isnull(local!selection)
                ),
                a!columnsLayout(
                  columns: {
                    a!columnLayout(
                      contents: {
                        a!textField(
                          label: "Name",
                          value: local!selectedEmployee.name,
                          readOnly: true
                        ),
                        a!textField(
                          label: "Department",
                          value: local!selectedEmployee.age,
                          readOnly: true
                        )
                      },
                      width: "MEDIUM"
                    ),
                    a!columnLayout(
                      contents: {
                        /* In the following fields, we display from, and save to
                           local!selectedEmployee. */
                        a!textField(
                          label: "Role",
                          value: local!selectedEmployee.role,
                          saveInto: local!selectedEmployee.role,
                          readOnly: local!readOnly
                        ),
                        /* Because dropdown components can't be readOnly, we use a textField to
                           display the value and an if() statement to swap it out for the dropdown
                           when it's time to edit. */
                        if(
                          local!readOnly,
                          a!textField(
                            label: "Team",
                            value: local!selectedEmployee.team,
                            readOnly: true
                          ),
                          a!dropdownField(
                            label: "Team",
                            choiceLabels: local!teamList,
                            choiceValues: local!teamList,
                            value: local!selectedEmployee.team,
                            saveInto: local!selectedEmployee.team,
                            disabled: local!readOnly
                          )
                        ),
                        /* The link enables editing in the other components, and is hidden when
                           editing is enabled. */
                        
                      },
                      width: "WIDE"
                    )
                  },
                  showWhen: not(isnull(local!selection))
                )
              }
            ),
            
          }
        )
      }
    )
  }
)

  Discussion posts and replies are publicly visible

  • 0
    Certified Lead Developer

    Hi Mana,

    Your rand() function is being called every time the component interacts. Try adding a field to your employees' variable and calling them in the grid column. It will work. Try the new code. 

    a!localVariables(
      /* We load the employee data into this variable. If you are populating
         this variable with a query, you would put .data at the end before passing
         it to the grid. */
      local!employees: 
    {
        a!map(
          id: 11,
          name: "Elizabeth Ward",
          role: "Senior Engineer",
          team: "Front-End Components",
          assessmentScore:rand(1),
          pto: 15,
          startDate: today() - 500
        ),
        a!map(
          id: 22,
          name: "Michael Johnson",
          role: "Payroll Manager",
          team: "Accounts Payable",
          assessmentScore:rand(1),
          pto: 2,
          startDate: today() - 100
        ),
        a!map(
          id: 33,
          name: "John Smith",
          role: "Quality Engineer",
          team: "User Acceptance Testing",
          assessmentScore:rand(1),
          pto: 5,
          startDate: today() - 1000
        ),
        a!map(
          id: 44,
          name: "Diana Hellstrom",
          role: "UX Designer",
          team: "User Experience",
          assessmentScore:rand(1),
          pto: 49,
          startDate: today() - 1200
        ),
        a!map(
          id: 55,
          name: "Francois Morin",
          role: "Account Executive",
          team: "Commercial North America",
          assessmentScore:rand(1),
          pto: 15,
          startDate: today() - 700
        ),
        a!map(
          id: 66,
          name: "Maya Kapoor",
          role: "Regional Director",
          team: "Front-End Components",
          assessmentScore:rand(1),
          pto: 15,
          startDate: today() - 1400
        ),
        a!map(
          id: 77,
          name: "Anthony Wu",
          role: "Benefits Coordinator",
          team: "Accounts Payable",
          assessmentScore:rand(1),
          pto: 2,
          startDate: today() - 300
        ),
    
      },
      /*refreshOnReferencedVarChange: false),*/
      /* local!teamList would normally come from a constant or data source. */
      local!teamList: {
        "Accounts Payable",
        "User Acceptance Testing",
        "User Experience",
        "Commercial North America",
        "Front-End Components"
      },
      /* This variable is for storing the grid's selection. */
      local!selection,
      /* This variable is used to for the full row of data on the selected item
         to be passed to the details section of the interface. */
      local!selectedEmployee,
      local!readOnly: true,
      {
        a!columnsLayout(
          columns: {
            a!columnLayout(
              contents: {
                a!sectionLayout(
                  label: "Employees",
                  contents: {
                    a!gridField(
                      data: local!employees,
                      columns: {
                        a!gridColumn(label: "Name", value: fv!row.name),
                        a!gridColumn(
                          label: "Assessment Score",
                          value: a!richTextDisplayField(
                            value: if(
                              todecimal(fv!row.assessmentScore) < 0.5,
                              /*rand(1)<0.5,*/
                              a!richTextIcon(icon: "thumbs-up", color: "POSITIVE"),
                              a!richTextIcon(icon: "thumbs-down", color: "NEGATIVE")
                            )
                          ),
                          align: "CENTER"
                        ),
                        a!gridColumn(
                          align: "CENTER",
                          label: "Show Details",
                          value: a!richTextDisplayField(
                            value: a!richTextIcon(
                              icon: "search-plus",
                              link: a!dynamicLink(
                                value: fv!row,
                                saveInto: {local!selectedEmployee,local!selection}
    
                              ),
                              linkStyle: "STANDALONE"
                            )
                          )
                        )
                      },
                      pageSize: 10,
                      shadeAlternateRows: false,
                      rowHeader: 1
                    )
                  }
                )
              }
            ),
            a!columnLayout(
              contents: {
                a!sectionLayout(
                  label: "Details",
                  contents: {
                    a!richTextDisplayField(
                      value: a!richTextItem(
                        text: "No employee selected.",
                        color: "SECONDARY",
                        size: "MEDIUM",
                        style: "EMPHASIS"
                      ),
                      showWhen: isnull(local!selection)
                    ),
                    a!columnsLayout(
                      columns: {
                        a!columnLayout(
                          contents: {
                            a!textField(
                              label: "Name",
                              value: local!selectedEmployee.name,
                              readOnly: true
                            ),
                            a!textField(
                              label: "Department",
                              value: local!selectedEmployee.age,
                              readOnly: true
                            )
                          },
                          width: "MEDIUM"
                        ),
                        a!columnLayout(
                          contents: {
                            /* In the following fields, we display from, and save to
                               local!selectedEmployee. */
                            a!textField(
                              label: "Role",
                              value: local!selectedEmployee.role,
                              saveInto: local!selectedEmployee.role,
                              readOnly: local!readOnly
                            ),
                            /* Because dropdown components can't be readOnly, we use a textField to
                               display the value and an if() statement to swap it out for the dropdown
                               when it's time to edit. */
                            if(
                              local!readOnly,
                              a!textField(
                                label: "Team",
                                value: local!selectedEmployee.team,
                                readOnly: true
                              ),
                              a!dropdownField(
                                label: "Team",
                                choiceLabels: local!teamList,
                                choiceValues: local!teamList,
                                value: local!selectedEmployee.team,
                                saveInto: local!selectedEmployee.team,
                                disabled: local!readOnly
                              )
                            ),
                            /* The link enables editing in the other components, and is hidden when
                               editing is enabled. */
    
                          },
                          width: "WIDE"
                        )
                     
                      },
                      showWhen: not(isnull(local!selection))
                    )
                  }
                ),
    
              }
            )
          }
        )
      }
    )

  • Hi,

    rand() function evaluates on each user interaction.

    you can try below code to stop that

    a!localVariables(
      /* We load the employee data into this variable. If you are populating
         this variable with a query, you would put .data at the end before passing
         it to the grid. */
      local!employees: {
        a!map(
          id: 11,
          name: "Elizabeth Ward",
          role: "Senior Engineer",
          team: "Front-End Components",
          pto: 15,
          startDate: today() - 500
        ),
        a!map(
          id: 22,
          name: "Michael Johnson",
          role: "Payroll Manager",
          team: "Accounts Payable",
          pto: 2,
          startDate: today() - 100
        ),
        a!map(
          id: 33,
          name: "John Smith",
          role: "Quality Engineer",
          team: "User Acceptance Testing",
          pto: 5,
          startDate: today() - 1000
        ),
        a!map(
          id: 44,
          name: "Diana Hellstrom",
          role: "UX Designer",
          team: "User Experience",
          pto: 49,
          startDate: today() - 1200
        ),
        a!map(
          id: 55,
          name: "Francois Morin",
          role: "Account Executive",
          team: "Commercial North America",
          pto: 15,
          startDate: today() - 700
        ),
        a!map(
          id: 66,
          name: "Maya Kapoor",
          role: "Regional Director",
          team: "Front-End Components",
          pto: 15,
          startDate: today() - 1400
        ),
        a!map(
          id: 77,
          name: "Anthony Wu",
          role: "Benefits Coordinator",
          team: "Accounts Payable",
          pto: 2,
          startDate: today() - 300
        ),
        
      },
      /* local!teamList would normally come from a constant or data source. */
      local!teamList: {
        "Accounts Payable",
        "User Acceptance Testing",
        "User Experience",
        "Commercial North America",
        "Front-End Components"
      },
      /* This variable is for storing the grid's selection. */
      local!selection,
      /* This variable is used to for the full row of data on the selected item
         to be passed to the details section of the interface. */
      local!selectedEmployee,
      local!readOnly: true,
      {
        a!columnsLayout(
          columns: {
            a!columnLayout(
              contents: {
                a!sectionLayout(
                  label: "Employees",
                  contents: {
                    a!gridField(
                      data: local!employees,
                      columns: {
                        a!gridColumn(label: "Name", value: fv!row.name),
                        a!gridColumn(
                          label: "Assessment Score",
                          value: a!richTextDisplayField(
                            value: a!localVariables(
                              local!rand: rand(),
                              if(
                                local!rand < 0.5,
                                a!richTextIcon(icon: "thumbs-up", color: "POSITIVE"),
                                a!richTextIcon(icon: "thumbs-down", color: "NEGATIVE")
                              )
                            )
                          ),
                          align: "CENTER"
                        ),
                        a!gridColumn(
                          align: "CENTER",
                          label: "Show Details",
                          value: a!richTextDisplayField(
                            value: a!richTextIcon(
                              icon: "search-plus",
                              link: a!dynamicLink(
                                value: fv!row,
                                saveInto: { local!selectedEmployee, local!selection }
                              ),
                              linkStyle: "STANDALONE"
                            )
                          )
                        )
                      },
                      pageSize: 10,
                      shadeAlternateRows: false,
                      rowHeader: 1,
                      refreshOnReferencedVarChange: false
                    )
                  }
                )
              }
            ),
            a!columnLayout(
              contents: {
                a!sectionLayout(
                  label: "Details",
                  contents: {
                    a!richTextDisplayField(
                      value: a!richTextItem(
                        text: "No employee selected.",
                        color: "SECONDARY",
                        size: "MEDIUM",
                        style: "EMPHASIS"
                      ),
                      showWhen: isnull(local!selection)
                    ),
                    a!columnsLayout(
                      columns: {
                        a!columnLayout(
                          contents: {
                            a!textField(
                              label: "Name",
                              value: local!selectedEmployee.name,
                              readOnly: true
                            ),
                            a!textField(
                              label: "Department",
                              value: local!selectedEmployee.age,
                              readOnly: true
                            )
                          },
                          width: "MEDIUM"
                        ),
                        a!columnLayout(
                          contents: {
                            /* In the following fields, we display from, and save to
                               local!selectedEmployee. */
                            a!textField(
                              label: "Role",
                              value: local!selectedEmployee.role,
                              saveInto: local!selectedEmployee.role,
                              readOnly: local!readOnly
                            ),
                            /* Because dropdown components can't be readOnly, we use a textField to
                               display the value and an if() statement to swap it out for the dropdown
                               when it's time to edit. */
                            if(
                              local!readOnly,
                              a!textField(
                                label: "Team",
                                value: local!selectedEmployee.team,
                                readOnly: true
                              ),
                              a!dropdownField(
                                label: "Team",
                                choiceLabels: local!teamList,
                                choiceValues: local!teamList,
                                value: local!selectedEmployee.team,
                                saveInto: local!selectedEmployee.team,
                                disabled: local!readOnly
                              )
                            ),
                            /* The link enables editing in the other components, and is hidden when
                               editing is enabled. */
                            
                          },
                          width: "WIDE"
                        )
                      },
                      showWhen: not(isnull(local!selection))
                    )
                  }
                ),
                
              }
            )
          }
        )
      }
    )

  • 0
    Certified Lead Developer

    I see Sanchit already beat me to the suggestion of loading the rand() value into a row-internal local variable - but I'm posting my code anyway because I took the extra 3 minutes to build you a better "show details" icon that also indicates the row you're looking at and collapses it when re-clicked.

    Note I also simplified the "local!selection" variable to just hold the ID of the selected row, since otherwise the whole CDT value was just being duplicated across both.  That just makes it easier to handle the comparison operators, etc.

    a!localVariables(
      /* We load the employee data into this variable. If you are populating
         this variable with a query, you would put .data at the end before passing
         it to the grid. */
      local!employees: {
        a!map(
          id: 11,
          name: "Elizabeth Ward",
          role: "Senior Engineer",
          team: "Front-End Components",
          pto: 15,
          startDate: today() - 500
        ),
        a!map(
          id: 22,
          name: "Michael Johnson",
          role: "Payroll Manager",
          team: "Accounts Payable",
          pto: 2,
          startDate: today() - 100
        ),
        a!map(
          id: 33,
          name: "John Smith",
          role: "Quality Engineer",
          team: "User Acceptance Testing",
          pto: 5,
          startDate: today() - 1000
        ),
        a!map(
          id: 44,
          name: "Diana Hellstrom",
          role: "UX Designer",
          team: "User Experience",
          pto: 49,
          startDate: today() - 1200
        ),
        a!map(
          id: 55,
          name: "Francois Morin",
          role: "Account Executive",
          team: "Commercial North America",
          pto: 15,
          startDate: today() - 700
        ),
        a!map(
          id: 66,
          name: "Maya Kapoor",
          role: "Regional Director",
          team: "Front-End Components",
          pto: 15,
          startDate: today() - 1400
        ),
        a!map(
          id: 77,
          name: "Anthony Wu",
          role: "Benefits Coordinator",
          team: "Accounts Payable",
          pto: 2,
          startDate: today() - 300
        ),
    
      },
      /* local!teamList would normally come from a constant or data source. */
      local!teamList: {
        "Accounts Payable",
        "User Acceptance Testing",
        "User Experience",
        "Commercial North America",
        "Front-End Components"
      },
      /* This variable is for storing the grid's selection. */
      local!selection,
      /* This variable is used to for the full row of data on the selected item
         to be passed to the details section of the interface. */
      local!selectedEmployee,
      local!readOnly: true,
      {
        a!columnsLayout(
          columns: {
            a!columnLayout(
              contents: {
                a!sectionLayout(
                  label: "Employees",
                  contents: {
                    a!gridField(
                      data: local!employees,
                      columns: {
                        a!gridColumn(label: "Name", value: fv!row.name),
                        a!gridColumn(
                          label: "Assessment Score",
                          value: a!localVariables(
                            local!score: a!refreshVariable(
                              value: rand(1)
                            ),
                            a!richTextDisplayField(
                              value: if(
                                local!score < 0.5,
                                a!richTextIcon(icon: "thumbs-up", color: "POSITIVE"),
                                a!richTextIcon(icon: "thumbs-down", color: "NEGATIVE")
                              )
                            )
                          ),
                          align: "CENTER"
                        ),
                        a!gridColumn(
                          align: "CENTER",
                          label: "Show Details",
                          value: a!richTextDisplayField(
                            value: {
                              a!richTextIcon(
                                icon: "search-plus",
                                caption: "Click to expand",
                                showWhen: tointeger(local!selection) <> fv!row.id,
                                link: a!dynamicLink(
                                  value: fv!row,
                                  saveInto: {
                                    local!selectedEmployee,
                                    a!save(local!selection, fv!row.id)
                                  }
                                ),
                                linkStyle: "STANDALONE"
                              ),
                              a!richTextIcon(
                                icon: "search-minus",
                                showWhen: tointeger(local!selection) = fv!row.id,
                                color: "NEGATIVE",
                                caption: "Click to collapse",
                                link: a!dynamicLink(
                                  value: fv!row,
                                  saveInto: {
                                    a!save(local!selection, null()),
                                    a!save(local!selectedEmployee, {})
                                  }
                                ),
                                linkStyle: "STANDALONE"
                              ),
                            }
                          )
                        )
                      },
                      pageSize: 10,
                      shadeAlternateRows: false,
                      rowHeader: 1
                    )
                  }
                )
              }
            ),
            a!columnLayout(
              contents: {
                a!sectionLayout(
                  label: "Details",
                  contents: {
                    a!richTextDisplayField(
                      value: a!richTextItem(
                        text: "No employee selected.",
                        color: "SECONDARY",
                        size: "MEDIUM",
                        style: "EMPHASIS"
                      ),
                      showWhen: isnull(local!selection)
                    ),
                    a!columnsLayout(
                      columns: {
                        a!columnLayout(
                          contents: {
                            a!textField(
                              label: "Name",
                              value: local!selectedEmployee.name,
                              readOnly: true
                            ),
                            a!textField(
                              label: "Department",
                              value: local!selectedEmployee.age,
                              readOnly: true
                            )
                          },
                          width: "MEDIUM"
                        ),
                        a!columnLayout(
                          contents: {
                            /* In the following fields, we display from, and save to
                               local!selectedEmployee. */
                            a!textField(
                              label: "Role",
                              value: local!selectedEmployee.role,
                              saveInto: local!selectedEmployee.role,
                              readOnly: local!readOnly
                            ),
                            /* Because dropdown components can't be readOnly, we use a textField to
                               display the value and an if() statement to swap it out for the dropdown
                               when it's time to edit. */
                            if(
                              local!readOnly,
                              a!textField(
                                label: "Team",
                                value: local!selectedEmployee.team,
                                readOnly: true
                              ),
                              a!dropdownField(
                                label: "Team",
                                choiceLabels: local!teamList,
                                choiceValues: local!teamList,
                                value: local!selectedEmployee.team,
                                saveInto: local!selectedEmployee.team,
                                disabled: local!readOnly
                              )
                            ),
                            /* The link enables editing in the other components, and is hidden when
                               editing is enabled. */
    
                          },
                          width: "WIDE"
                        )
                      },
                      showWhen: not(isnull(local!selection))
                    )
                  }
                ),
    
              }
            )
          }
        )
      }
    )

  • Hi Subhad:

    Thanks for your reply/suggestion - this solution works!  Meantime, I am trying to understand why the refreshOnReferencedVarChange is being trigged because as per the documentation "When true, grid data will be refreshed each time the value of any variable referenced in the data parameter is updated" - the default is true.  I am not changing any values in data parameter when the 'show details' icon is clicked.

    Ma

  • Hi Sachit:

    Your solution/suggestion works.  But I am wondering why the refreshOnReferencedVarChange is being trigged because as per the documentation "When true, grid data will be refreshed each time the value of any variable referenced in the data parameter is updated" - the default is true.  I am not changing any values in data parameter when the 'show details' icon is clicked.  Am I misunderstanding the concept?

    Ma

  • Mike, 

    Since I liked your idea of collapsing the details section when re-clicked and storing just the ID of the selected row instead of the whole CDT,  I copied and tried to test the Interface.  

    However, it gave me an error (nterface Definition: Expression evaluation error at function a!gridField [line 86]: A grid component [label="null"] has an invalid value for "columns". A grid column [label="Show Details"] has encountered an error. Expression evaluation error at function 'tointeger' [line 121]: Could not cast from Map to Number (Integer). Details: CastInvalidCould not cast from Map to Number (Integer). Details: CastInvalid).

    I will spend some time debugging and let you know the status.

    Thanks.

    Ma

  • 0
    Certified Lead Developer
    in reply to MaNa

    You should start by copying my entire code fresh into a blank interface editor.  When I do this (from scratch again just now), it works fine still, just like when I first pasted in your original to try with some edits.  If you pasted it overtop of your existing code, but you already had a value in your local variable for example, the tointeger() function might fail because it's unexpectedly being asked to run on the existing value of that variable which might be something invalid (the error message suggests that it contains map data, which is what it was originally storing).  Also, I'd expect this should normally be fixable, simply by pressing "TEST" again.

  • 0
    Certified Senior Developer
    in reply to MaNa

    You understood the concept right, you are not making any change in grid data when you are interacting with show details icon. But this isn't the reason why your assessment score icon is refreshing but it is due to the fact that rand() function evaluates after each user interaction.

    So whenever you click on show details icon, your rand() function returns different value and the OR condition output changes, due to which icons also change accordingly.

    To prevent that from happening we took advantage of localVariable (without any refresh variable configuration) inside grid row which by default (refreshOnReferencedVarChange is true) only refreshes when the value of any referenced variable is changed and since our expression is local!rand: rand(), so there is no variable used in the value, it will remain as is

  • Mike, 

    Starting from a new interface worked.  Trial by fire learning here - didn't realize that deleting old code and pasting your code wouldn't work.  Yeah, I should have tried the 'TEST' button - hitting that TEST button had worked in the past.  

    Thanks!

  • Sanchit, Thanks for the explanation - appreciate it!