Interface patterns give you an opportunity to explore different interface designs. Be sure to check out How to Adapt a Pattern for Your Application.
Allow a user to save their preferred filter on a report and automatically load it when they revisit the report later.
This scenario demonstrates:
Since users can save filters on a record list without any additional configuration, consider using the record list instead of using this recipe when displaying a grid of records.
For this recipe, you'll want to use a report with some actual data. If you've already set up the Update an Entity-Backed Record from its Summary View recipe you can use that recipe's entity-backed record, otherwise you can set it up now in only a few minutes by following these steps:
Customer Support Request System
in the Application Name field
Support Request
in the Record Singular Name fieldSupport Requests
in the Record Plural Name fieldYou've now created a fully-functioning application with an entity-backed record! To make sure you have some data to report on, go to Actions and start a few service requests.
Now on to the report! Before you put in the expression, you'll first need to create a place to store user filters:
SupportRequestReportFilter
in the Name fieldusername
for the first field's namestatus
for the second field's namepriority
for the third field's nameNow that you've created the data type, you'll need to make a data store entity so you can write the data to your database.
SupportRequestReportFilter
in the Name fieldSupportRequestReportFilter
in the Type fieldNow you need to create a constant pointing at the data store entity so it can be used in an expression:
CSRS_FILTER_ENTITY
in the Name fieldData Store Entity
for the Type fieldSupport Requests
for the Data Store fieldSupportRequestReportFilter
for the Entity fieldEnter CSRS Rules and Constants
in the Save In field, then select the folder from the suggestions
Now you're ready to build the actual report.
CSRS Rules and Constants
in the Save In field, then select the folder from the suggestions1
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
a!localVariables(
local!persistedFilterData: a!queryEntity(
entity: cons!CSRS_FILTER_ENTITY,
query: a!query(
filter: a!queryFilter(field: "username", operator: "=", value: loggedInUser()),
pagingInfo: a!pagingInfo(startIndex: 1, batchSize: 1)
),
fetchTotalCount: true
),
local!persistedFilter: if(
local!persistedFilterData.totalCount = 0,
/* There's no existing filter for this user, so create a new one */
'type!{urn:com:appian:types}SupportRequestReportFilter'(username: loggedInUser()),
cast('type!{urn:com:appian:types}SupportRequestReportFilter', local!persistedFilterData.data[1])
),
local!saveFilterError: false,
/* Store the current filter separate from the persisted filter so we know when they are the same */
local!filter: local!persistedFilter,
local!allPriorities: rule!CSRS_GetAllPriority().value,
local!allStatuses: rule!CSRS_GetAllStatus().value,
local!pagingInfo: a!pagingInfo(1, -1, a!sortInfo("createdOn", false)),
local!filterChanged: not(exact(local!persistedFilter, local!filter)),
/* Data that will be displayed in the grid given the *
* current search terms and applied filters */
{
a!sectionLayout(
contents:{
a!columnsLayout(
columns:{
a!columnLayout(
contents:{
a!dropdownField(
label: "Priority",
labelPosition: "ADJACENT",
placeholder: "All Priorities",
choiceLabels: local!allPriorities,
choiceValues: local!allPriorities,
value: local!filter.priority,
saveInto: local!filter.priority
),
a!dropdownField(
label: "Status",
labelPosition: "ADJACENT",
placeholder: "All Statuses",
choiceLabels: local!allStatuses,
choiceValues: local!allStatuses,
value: local!filter.status,
saveInto: local!filter.status
)
}
),
a!columnLayout(
contents:{
a!buttonLayout(
secondaryButtons: {
if(
local!saveFilterError,
a!buttonWidget(
label: "Could not save filters",
disabled: true
),
a!buttonWidget(
label: "Save Filters",
disabled: not(local!filterChanged),
saveInto: a!writeToDataStoreEntity(
dataStoreEntity: cons!CSRS_FILTER_ENTITY,
valueToStore: local!filter,
onSuccess: {
a!save(local!persistedFilter, local!filter)
},
onError: {
a!save(local!saveFilterError, true)
}
)
)
)
}
)
}
)
}
)
}
),
a!gridField(
emptyGridMessage: "No Support Requests available",
data: a!queryEntity(
entity: cons!CSRS_SUPPORT_REQUEST_DSE,
query: a!query(
selection: a!querySelection(
columns: {
a!queryColumn(field: "id"),
a!queryColumn(field: "title"),
a!queryColumn(field: "status"),
a!queryColumn(field: "priority")
}
),
logicalExpression: a!queryLogicalExpression(
operator: "AND",
filters: {
a!queryFilter(
field: "status.value",
operator: "=",
value: local!filter.status
),
a!queryFilter(
field: "priority.value",
operator: "=", value:
local!filter.priority
)
},
ignoreFiltersWithEmptyValues: true
),
pagingInfo: fv!pagingInfo
),
fetchTotalCount: true
),
columns: {
a!gridColumn(
label: "Title",
sortField: "title",
value: fv!row.title
),
a!gridColumn(
label: "Status",
sortField: "status.value",
value: index(fv!row.status, "value", {})
),
a!gridColumn(
label: "Priority",
sortField: "priority.value",
value: a!imageField(
images: rule!CSRS_GetIconForPriority(index(fv!row.priority, "value", {}))
),
width: "NARROW",
align: "CENTER"
),
/*a!gridColumn(*/
/*label: "Priority",*/
/*sortField: "priority.value",*/
/*value: a!richTextDisplayField(*/
/*value: a!richTextIcon(*/
/*icon: displayvalue(*/
/*index(fv!row.priority, "value", {}),*/
/* Priority values */
/*{"Low", "Medium", "High", "Critical"},*/
/* Corresponding icons for each priority */
/*{"arrow-circle-down", "arrow-circle-right", "arrow-circle-up", "exclamation-circle"},*/
/*"circle"*/
/*),*/
/*size: "MEDIUM",*/
/*color: if(*/
/*contains(*/
/*{"High", "Critical"},*/
/*index(fv!row.priority, "value", {}),*/
/*),*/
/*"NEGATIVE",*/
/*"SECONDARY"*/
/*)*/
/*)*/
/*),*/
/*align: "CENTER",*/
/*width: "NARROW"*/
/*)*/
},
rowHeader: 1
)
}
)
a!localVariables()
variables so that they can be compared. Not only does this mean the user knows when they have changed the filter (because the button is enabled) but also provides feedback that the filters have been saved (when it becomes disabled).onError
parameter is used to change the button label.See also: Smart Services in SAIL