Free cookie consent management tool by TermsFeed

Limit the Number of Rows in a Grid That Can Be Selected

Tip:  Interface patterns give you an opportunity to explore different interface designs. Be sure to check out How to Adapt a Pattern for Your Application.

Goal

Limit the number of rows that can be selected to an arbitrary number.

Note:  This expression uses direct references to the Employee record type, created in the Records Tutorial. If you've completed that tutorial in your environment, you can change the existing record-type references in this pattern to point to your Employee record type instead.

This is a more elaborate version of the Limit Grid Selection to One Row pattern.

limit-number-of-rows-selected.png

This scenario demonstrates:

  • How to configure grid selection in a Read-Only Grid.
  • How to limit selection to an arbitrary number.

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
a!localVariables(
  local!selection,
  local!selectedRows,
  /* This is the maximum number of rows you can select from the grid. Selections that exceed
     this value are dropped from local!selectedRows. */
  local!selectionLimit: 2,
  /* This stores the last dropped row that exceeded the selection limit. */
  local!errorDrop,
  {
    a!columnsLayout(
      columns: {
        a!columnLayout(
          contents: {
            a!gridField(
              label: "Employees",
              labelPosition: "ABOVE",
              instructions: "Select up to " & local!selectionLimit & " employees.",
              data: recordType!Employee,
              columns: {
                a!gridColumn(
                  label: "ID",
                  sortField: "id",
                  value: fv!row[recordType!Employee.fields.id],
                  width: "ICON"
                ),
                a!gridColumn(
                  label: "First Name",
                  sortField: "firstName",
                  value: fv!row[recordType!Employee.fields.firstName]
                ),
                a!gridColumn(
                  label: "Last Name",
                  sortField: "lastName",
                  value: fv!row[recordType!Employee.fields.lastName]
                ),
                a!gridColumn(
                  label: "Phone Number",
                  sortField: "phoneNumber",
                  value: fv!row[recordType!Employee.fields.phoneNumber]
                )
              },
              pagesize: 10,
              selectable: true,
              selectionstyle: "ROW_HIGHLIGHT",
              selectionvalue: local!selection,
              selectionsaveinto: {
                local!selection,
                a!save(local!selectedRows, append(local!selectedRows, fv!selectedRows)),
                a!save(local!selectedRows, difference(local!selectedRows, fv!deselectedRows)),
                /* If the length of the selected rows is greater than the limit, this saves the excess
                   selection in local!errorDrop so we can tell the user which row was dropped. */
                if(length(local!selectedRows) > local!selectionLimit, 
                  a!save(local!errorDrop, fv!selectedRows),
                  a!save(local!errorDrop, null)
                ),
                /* We use the rdrop() function to remove the most recent selections, so only the
                   first-selected rows, up to the limit, remain. If you want the reverse behavior, 
                   dropping the oldest selections instead, replace rdrop() with ldrop().

                   The max() function is used as a simple way to handle negative numbers for when 
                   the selection length is less than the limit. */
                a!save(local!selectedRows, rdrop(local!selectedRows, max(0, length(local!selectedRows)-local!selectionLimit))),
                a!save(local!selection, rdrop(local!selection, max(0, length(local!selection)-local!selectionLimit)))
              },
              validations: a!validationMessage(
                message: "The total cannot be greater than $1,000",
                validateAfter: "REFRESH",
                showWhen: true
              )
            )
          },
          width: "WIDE"
        ),
        a!columnLayout(
          contents: {
            a!sectionLayout(
              label: "Selected Employees",
              contents: {
                a!forEach(
                  items: local!selectedRows,
                  expression: a!textField(
                    label: fv!index&". "&fv!item[recordType!Employee.fields.firstName]&" "&fv!item[recordType!Employee.fields.lastName],
                    value: "    "&fv!item[recordType!Employee.fields.phoneNumber],
                    readOnly: true
                  )
                )
              }
            ),
            a!richTextDisplayField(
              label: "Rich Text",
              labelPosition: "COLLAPSED",
              value: {
                a!richTextItem(
                  text: {
                    if(
                      not(isnull(local!errorDrop)),
                      "Can't add "
                      &local!errorDrop[recordType!Employee.fields.firstName] &" "& local!errorDrop[recordType!Employee.fields.lastName] &"."
                      &char(10)&"Maximum selections: "&local!selectionLimit,
                      ""
                    )
                  },
                  color: "NEGATIVE",
                  style: {
                    "STRONG"
                  }
                )
              }
            )
          }
        )
      }
    )
  }
)

Test it out

  1. Select multiple rows and note that only the last selection persists.

Feedback