Use Links in a Grid to Show More Details About an Object

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

Display more of an object's data than can fit in a single row in a read-only paging 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.

Rather than placing all the data in the grid, have the user select a row by clicking on a link, and show the row details in a separate section of the form.

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

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
=load(
  local!selectedEmployeeId,
  local!pagingInfo: a!pagingInfo(startIndex: 1, batchSize: 5),
  with(
    local!datasubset: a!queryEntity(
      entity:cons!EMPLOYEE_ENTITY,
      query:a!query(
        selection: a!querySelection(columns: {
          /* Alias can be used to remane field*/
          a!queryColumn(field: "firstName" ),
          a!queryColumn(field: "lastName"),
          /* 
          * For nested CDTs using an alias is helpful. If department was nested, you could configure
          * the queryColumn like this: a!queryColumn(field:"department.name", alias:"dept") and
          * use "dept" in your grid text columns.
          */
          a!queryColumn(field: "department"),
          a!queryColumn(field: "title"),
          a!queryColumn(field: "phoneNumber"),
          a!queryColumn(field: "startDate")
        }),
        pagingInfo: local!pagingInfo
      ),
      fetchTotalCount: true
    ),
    /* Formats first and last name columns into an array of dictionaries*/
    local!names:merge(
      index(local!datasubset.data, "firstName", null),
      index(local!datasubset.data, "lastName", null)
    ),
    {
      a!sectionLayout(
          label: "Employees",
          contents: {
            a!gridField(
              totalCount: local!datasubset.totalCount,
              columns: {
                a!gridTextColumn(
                  label: "Name",
                  data: a!forEach(
                    items:local!names,
                    expression: joinarray(fv!item," ")
                  ),
                  /* Creates a dynamic link for every item in local!datasubset `*/
                  links: a!forEach(
                    items: local!datasubset.identifiers,
                    expression: a!dynamicLink(value: fv!item, saveInto: local!selectedEmployeeId)
                  )
                ),
                a!gridTextColumn(
                  label: "Department",
                  data: index(local!datasubset.data, "department", null)
                )
              },
              value: local!pagingInfo,
              saveInto: local!pagingInfo,
              rowHeader: 1
            )
          }
        ),
      with(
        /*` Replace with your rule to get the employee details */
        local!selectedEmployee: displayvalue(local!selectedEmployeeId, local!datasubset.identifiers, local!datasubset.data, {}),
        a!sectionLayout(
          showWhen:not( isnull( local!selectedEmployeeId ) ),
          label: "Details About " & local!selectedEmployee.firstName & " " & local!selectedEmployee.lastName,
          contents: {
            a!columnsLayout(
              columns:{
                a!columnLayout(
                  contents:{
                    a!textField(
                      label: "Phone Number",
                      labelPosition: "ADJACENT",
                      value: local!selectedEmployee.phoneNumber,
                      readOnly: true
                    ),
                    a!textField(
                      label: "Department",
                      labelPosition: "ADJACENT",
                      value: local!selectedEmployee.department,
                      readOnly: true
                    )
                  }
                ),
                a!columnLayout(
                  contents: {
                    a!textField(
                      label: "Title",
                      labelPosition: "ADJACENT",
                      value: local!selectedEmployee.title,
                      readOnly: true
                    ),
                    a!dateField(
                      label: "Start Date",
                      labelPosition: "ADJACENT",
                      value: local!selectedEmployee.startDate,
                      readOnly: true
                    )
                  }
                )
              }
            )
          }
        )
      )  
    }
  )
)

Test it out

  1. Click on the names in the grid in the left column. Notice how the value in the fields in the right column change to reflect the name you most recently clicked on.
FEEDBACK