Understanding User and Group Browser Components

Example Interfaces

The following sections provide example interface expressions aimed at explaining both how the Group Browser and User Browser components work and how they can be configured to achieve different goals.

  1. Navigation & the Initial Group
  2. Selection for More Information
  3. Selection for Picking

The user and group browsers provide an easy way to show group membership trees to users. By only specifying three values in the component, users will be able to navigate through a group's membership.

In this simple example, a company has all departments as groups, departments have sub-departments, and all top-level departments stem from a single group called "Departments." To create a browser that allows users to navigate the departmental structure of this company, you need a constant and an interface. In the interface, you need a group browser with only the Initial Group, Navigation Path, and Save Navigation To specified. In this theoretical use case, the designer would use a constant that points to the "Departments" group to set the initial group. In the expression below, the constant has been replaced with a local variable and a picker so that you can easily try it out for yourself.

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
load(
  local!initialGroup,
  local!navigationPath,
  {
    a!sectionLayout(
      label: "Initial Group",
      contents: {
        a!pickerFieldGroups(
          label: "Select a Group",
          maxSelections: 1,
          value: local!initialGroup,
          saveInto: {
            local!initialGroup,
            a!save(
              local!navigationPath,
              {}
            )
          }
        )
      }
    ),
    a!sectionLayout(
      label: "Example Interface",
      contents: {
        a!groupBrowserFieldColumns(
          rootGroup: local!initialGroup,
          pathValue: local!navigationPath,
          pathSaveInto: local!navigationPath
        )
      }
    )
  }
)

Read the following paragraphs for explanation of the above interface.

First, the Initial Group, or initial group, is a group that represents the starting point of navigation. The initial group's members are shown in the first column of the browser.

Any remaining columns are generated by the Navigation Path, or navigation path. For each group in the navigation path, a new column appears showing that group's members. A user can also be in the navigation path, but that is only for the purpose of selection. The first user or group in the Navigation Path must be a member of the Initial Group. Each subsequent user or group in the Navigation Path must be a member of the group that comes before it in the array.

Normally, the navigation path starts out as an empty rule input or local variable, though there are exceptions (See Add, Remove, and Move Group Members). The type of the navigation path should either be a group array if using the group browser or a people array if using either of the other browsers. In either case, the variable set as the navigation path should always be included in the Save Navigation To. When a user clicks on a user or group, the value sent to the Save Navigation To is the path of group membership taken to get from the initial group to the clicked user or group. To see the saved values for yourself, see the example on the group browser page.

Selection for More Information

In many cases, when a user or group is selected, more information on the group needs to be provided to the user. Selection is useful for these cases. Because any user or group can be a member of multiple groups, the hierarchy represented here is complex and takes five variables to represent: Initial Group, Navigation Path, Save Navigation To, Selection Value, and Save Selection To. The first three fields are necessary to allow a user to navigate through the membership; the latter two allow users to select a user or group and have the selection display in the browser.

Building off the example from the Navigation & Initial Group section, imagine a company where all departments are structured hierarchically under a "Departments" group. Now, users want the ability select a user member and view information about that user. When setting the initial group, the designer should use a constant that points to the "Departments" group. In the expression below, the constant has been replaced with a local variable and a picker so that you can easily try it out for yourself.

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
load(
  local!initialGroup,
  local!navigationPath,
  local!selectionValue,
  {
    a!sectionLayout(
      label: "Initial Group",
      contents: {
        a!pickerFieldGroups(
          label: "Select a Group",
          maxSelections: 1,
          value: local!initialGroup,
          saveInto: {
            local!initialGroup,
            a!save(
              local!navigationPath,
              {}
            )
          }
        )
      }
    ),
    a!sectionLayout(
      label: "Example Interface",
      contents: {
        a!userBrowserFieldColumns(
          label: "Select a User",
          rootGroup: local!initialGroup,
          pathValue: local!navigationPath,
          pathSaveInto: {
            local!navigationPath,
            a!save(
              local!selectionValue,
              null
            )
          },
          selectionValue: local!selectionValue,
          selectionSaveInto: local!selectionValue
        )
      }
    ),
    a!sectionLayout(
      showWhen: not(
        isnull(
          local!selectionValue
        )
      ),
      contents: {
        a!columnsLayout(
          columns: {
            a!columnLayout(
              contents: {
                a!textField(
                  label: "First Name",
                  value: user(
                    local!selectionValue,
                    "firstName"
                  ),
                  readOnly: true
                ),
                a!textField(
                  label: "Last Name",
                  value: user(
                    local!selectionValue,
                    "lastName"
                  ),
                  readOnly: true
                ),
                a!textField(
                  label: "Supervisor",
                  value: user(
                    local!selectionValue,
                    "supervisorName"
                  ),
                  readOnly: true
                )
              }
            ),
            a!columnLayout(
              contents: {
                a!textField(
                  label: "E-mail",
                  value: user(
                    local!selectionValue,
                    "email"
                  ),
                  readOnly: true
                ),
                a!textField(
                  label: "Address",
                  value: concat(
                    user(
                      local!selectionValue,
                      "address1"
                    ),
                    char(
                      10
                    ),
                    user(
                      local!selectionValue,
                      "address2"
                    ),
                    char(
                      10
                    ),
                    user(
                      local!selectionValue,
                      "address3"
                    ),
                    char(
                      10
                    ),
                    user(
                      local!selectionValue,
                      "city"
                    ),
                    ", ",
                    user(
                      local!selectionValue,
                      "state"
                    ),
                    char(
                      10
                    ),
                    user(
                      local!selectionValue,
                      "zipCode"
                    )
                  ),
                  readOnly: true
                )
              }
            )
          }
        )
      }
    )
  }
)

What you may notice when trying out the above interface is that the Selection Value does not clear when selecting a group, even though the selection is not visible. See the Selection for Picking section to see why this can be useful. If, however, you want the selection to be cleared when not clicking on a user, simply add a save to the Save Navigation To which clears out the Selection Value. See the interface below for an example.

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
load(
  local!initialGroup,
  local!navigationPath,
  local!selectionValue,
   {
      a!sectionLayout(
        label: "Initial Group",
        contents: {
          a!pickerFieldGroups(
            label: "Select a Group",
            maxSelections: 1,
            value: local!initialGroup,
            saveInto: {
              local!initialGroup,
              a!save(local!navigationPath, {})
            }
          )
        }
      ),
      a!sectionLayout(
        label: "Example Interface",
        contents: {
          a!userBrowserFieldColumns(
            label: "Select a User",
            rootGroup: local!initialGroup,
            pathValue: local!navigationPath,
            pathSaveInto: {
              local!navigationPath,
              a!save(local!selectionValue, null)
            },
            selectionValue: local!selectionValue,
            selectionSaveInto: local!selectionValue
          )
        }
      ),
      a!sectionLayout(
        showWhen: not(isnull(local!selectionValue)),
        contents: {
          a!columnsLayout(
            columns: {
              a!columnLayout(
                contents: {
                  a!textField(
                    label: "First Name",
                    value: user(local!selectionValue, "firstName"),
                    readOnly: true
                  ),
                  a!textField(
                    label: "Last Name",
                    value: user(local!selectionValue, "lastName"),
                    readOnly: true
                  ),
                  a!textField(
                    label: "Supervisor",
                    value: user(local!selectionValue, "supervisorName"),
                    readOnly: true
                  )
                }
              ),
              a!columnLayout(
                contents: {
                  a!textField(
                    label: "E-mail",
                    value: user(local!selectionValue, "email"),
                    readOnly: true
                  ),
                  a!textField(
                    label: "Address",
                    value: concat(
                      user(local!selectionValue, "address1"), char(10),
                      user(local!selectionValue, "address2"), char(10),
                      user(local!selectionValue, "address3"), char(10),
                      user(local!selectionValue, "city"), ", ",
                      user(local!selectionValue, "state"), char(10),
                      user(local!selectionValue, "zipCode")
                    ),
                    readOnly: true
                  )
                }
              )
            }
          )
        }
      )
    }
)

Selection for Picking

In the Selection for More Information section, the Selection Value was used to determine whose information was being displayed below the browser. This section demonstrates how to leverage the user and group browsers for picking users or groups.

Extending the example used in previous sections, imagine a company has an on-boarding process which requires an employee to choose the department of the new hire. A picker or browser alone would suffice, but combining the two creates a better user experience. The following expression demonstrates how a designer would configure the picker and browser combination. Note that you usually want to set the initial group as a constant. In the expression below, the constant has been replaced with a local variable and a picker so that you can easily try it out for yourself.

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
load(
  local!initialGroup,
  local!navigationPath,
  local!selectionValue,
  {
    a!sectionLayout(
      label: "Initial Group",
      contents: {
        a!pickerFieldGroups(
          label: "Select a Group",
          maxSelections: 1,
          value: local!initialGroup,
          saveInto: {
            local!initialGroup,
            a!save(
              local!navigationPath,
              {}
            )
          }
        )
      }
    ),
    a!sectionLayout(
      label: "Example Interface",
      contents: {
        a!groupBrowserFieldColumns(
          rootGroup: local!initialGroup,
          pathValue: local!navigationPath,
          pathSaveInto: local!navigationPath,
          selectionValue: local!selectionValue,
          selectionSaveInto: local!selectionValue
        ),
        a!pickerFieldGroups(
          label: "Department",
          labelPosition: "ADJACENT",
          required: true,
          groupFilter: local!initialGroup,
          maxSelections: 1,
          value: local!selectionValue,
          saveInto: local!selectionValue
        )
      }
    )
  }
)

A few of important items to note about the above example:

  1. Selection Value is set as the value of the picker so that there is no discrepancy between the browser and picker.
  2. In the picker, groupFilter is set to the initial group to ensure that the user does not choose an invalid group.
  3. The picker sets maxSelections to "1" to ensure that multiple items are not chosen. The browsers do not support multiple selection.
  4. The picker is set as required. The browsers do not have validation, so any validations should be set on paired components.
  5. When the user uses the picker to choose a group, the display in the browser does not change to focus on the chosen group.
  6. If the action taken requires processing, such as moving a group member, then the local variables should be changed to rule inputs.
FEEDBACK