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

Parents
  • 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))
                    )
                  }
                ),
    
              }
            )
          }
        )
      }
    )

Reply
  • 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))
                    )
                  }
                ),
    
              }
            )
          }
        )
      }
    )

Children
  • 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.

  • 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!