Use Links in a Grid to Show More Details and Edit Data

Interface patterns give you an opportunity to explore different interface designs. To learn how to directly use patterns within your interfaces, see How to Adapt a Pattern for Your Application.

Goal

Allow end users to click a link in a read-only paging grid to view the details for the row, and make changes to the data. The data available for editing may include more fields than are displayed in the grid.

This recipe uses an employee data structure and objects created through the Use the Write to Data Store Entity Smart Service Function on an Interface recipe. Make sure that recipes has been built first in order to see data in this recipe.

This design pattern is not recommended for offline interfaces because reflecting immediate changes in an interface based on user interaction requires a connection to the server.

This scenario demonstrates:

  • How to use links in a grid that conditionally display other interface components
  • How to allow editable fields to update the individual fields of the a data set

Expression

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
=load(
  /*  
  * local!employees is hard-coded here. If you were using this with yoour data, this
  * variable would be replaced with a rule input of CDT data type. All components referencing
  * local!employees should then be updated to point to your rule input.
  */
  local!employees: {
    { id: 1, firstName: "John" , lastName: "Smith" , department: "Engineering" , title: "Director" , phoneNumber: "555-123-4567" , startDate: today()-360 },
    { id: 2, firstName: "Michael" , lastName: "Johnson" , department: "Finance" , title: "Analyst" , phoneNumber: "555-987-6543" , startDate: today()-360 },
    { id: 3, firstName: "Mary", lastName: "Reed" , department: "Engineering" , title: "Software Engineer" , phoneNumber: "555-456-0123" , startDate: today()-240 },
    { id: 4, firstName: "Angela" , lastName: "Cooper" , department: "Sales" , title: "Manager" , phoneNumber: "555-123-4567" , startDate: today()-240 },
    { id: 5, firstName: "Elizabeth" , lastName: "Ward" , department: "Sales" , title: "Sales Associate" , phoneNumber: "555-987-6543" , startDate: today()-240 },
    { id: 6, firstName: "Daniel", lastName: "Lewis" , department: "HR" , title: "Manager" , phoneNumber: "555-876-5432" , startDate: today()-180 },
    { id: 7, firstName: "Paul" , lastName: "Martin" , department: "Finance" , title: "Analyst" , phoneNumber: "555-609-3691" , startDate: today()-150 },
    { id: 8, firstName: "Jessica" , lastName: "Peterson" , department: "Finance" , title: "Analyst" , phoneNumber: "555-987-6543" , startDate: today()-150 },
    { id: 9, firstName: "Mark" , lastName: "Hall" , department: "Professional Services" , title: "Director" , phoneNumber: "555-012-3456" , startDate: today()-150 }
  },
  /* store the current employee CDT  */
  local!employeeToUpdate,
  a!formLayout(
    contents:{
      if(
        isnull(local!employeeToUpdate),
        a!sectionLayout(
          label: "Employees",
          contents: {
            a!gridField(
              totalCount: count(local!employees),
              columns: {
                a!gridTextColumn(
                  label: "Name",
                  /* Joins local!name values with a space to properly format each person's name*/
                  data: a!forEach(
                    items:local!employees,
                    expression: fv!item.firstName & " " & fv!item.lastName
                  ),
                  /* Creates a dynamic link for every item in local!data */
                  links: a!forEach(
                    local!employees,
                    a!dynamicLink(value: fv!item, saveInto: local!employeeToUpdate)
                  )
                ),
                a!gridTextColumn(
                  label: "Department",
                  data: index(local!employees, "department", null)
                )
              },
              value: a!pagingInfo(
                startIndex: 1,
                batchSize: 10
              ),
              rowHeader: 1
            )
          }
        ),
        a!sectionLayout(
          label: "Update Details for: " & local!employeeToUpdate.firstName & " " & local!employeeToUpdate.lastName,
          contents: {
            a!linkField(
              labelPosition: "COLLAPSED",
              links: a!dynamicLink(
                label: "⇦ Back to list",
                value: null,
                saveInto: local!employeeToUpdate
              )
            ),
            a!columnsLayout(
              columns:{
                a!columnLayout(
                  contents:{
                    a!textField(
                      label: "First Name",
                      value: local!employeeToUpdate.firstName,
                      saveInto: local!employeeToUpdate.firstName
                    ),
                    a!textField(
                      label: "Phone Number",
                      value: local!employeeToUpdate.phoneNumber,
                      saveInto: local!employeeToUpdate.phoneNumber
                    ),
                    a!textField(
                      label: "Department",
                      value: local!employeeToUpdate.department,
                      saveInto: local!employeeToUpdate.department
                    )
                  } 
                ),
                a!columnLayout(
                  contents:{
                    a!textField(
                      label: "Last Name",
                      value: local!employeeToUpdate.lastName,
                      saveInto: local!employeeToUpdate.lastName
                    ),
                    a!dateField(
                      label: "Start Date",
                      value: local!employeeToUpdate.startDate,
                      saveInto: local!employeeToUpdate.startDate
                    ),
                    a!textField(
                      label: "Title",
                      value: local!employeeToUpdate.title,
                      saveInto: local!employeeToUpdate.title
                    )
                  }
                )
              }
            )
          }
        )
      )
    },
    buttons:a!buttonLayout(
      primaryButtons: {
        a!buttonWidget(
          label: "Save Update",
          style: "PRIMARY",
          value: local!employeeToUpdate.id,
          saveInto:{
            /* updates local!employess with the data that was save in the fields above */
            a!save(
              local!employees,
              updatearray(
                local!employees,
                wherecontains(
                  tointeger(save!value),
                  tointeger(local!employees.id)
                ),
                local!employeeToUpdate
              )
            ),
            a!save(local!employeeToUpdate,null)
          }
        )
      },
      secondaryButtons: {
        a!buttonWidget(
          label: "Cancel",
          value: null,
          saveInto: local!employeeToUpdate
        )
      },
      showWhen: not(isnull(local!employeeToUpdate))
    )
  )
)

Test it out

  1. Click on an employee's name in the grid's left column. Notice that an editable section appears.
  2. Change the employee's department and click the Save Update button. Notice that the employee's department has changed on the grid.
  3. Click on an employee's name, change the department and click Cancel. Notice that the employee's department has not changed

Notable Implementation Details

  • Not all data that is available for edit need to be represented in the grid and vice versa
  • A special character was used in the Back to List link above the editable fields. Alternatively, stylized rich text could be used to generate a link label for a similar effect.
  • Hard-coded data is used to populate the employee grid and fields. Typically, this data would be passed in via a rule input or queried from some 3rd party data source.
FEEDBACK