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.
Create a grid that shows hierarchical data and allows users to dynamically expand and collapse rows within the grid.
This scenario demonstrates:
For this recipe, you'll need two Data Store Entities that are populated with data:
PurchaseRequest
with the following fields:
PurchaseRequestItem
with the following fields:
Insert the following values into PurchaseRequest
:
id | summary |
---|---|
1 | PR 1 |
2 | PR 2 |
Insert the following values into PurchaseRequestItem
:
id | summary | qty | unitPrice | purchaseRequest.id |
---|---|---|---|---|
1 | Item 1 | 2 | 10 | 1 |
2 | Item 2 | 3 | 50 | 1 |
3 | Item 3 | 1 | 100 | 1 |
4 | Item 4 | 3 | 75 | 2 |
5 | Item 5 | 10 | 25 | 2 |
Now that we have the data, let's create a couple of supporting constants:
PR_ENTITY
: A constant of type Data Store Entity with value PurchaseRequests
.PR_ITEM_ENTITY
: A constant of type Data Store Entity with value PurchaseRequestItems
.Now that we have created all of the supporting objects, let's move on to the main 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
a!localVariables(
local!prs: a!queryEntity(
entity: cons!PR_ENTITY,
query: a!query(
/* To return all fields, leave the selection parameter blank. `*/
/*`If you are not displaying all fields, use the selection `*/
/*` parameter to only return the necessary fields */
pagingInfo: a!pagingInfo(startIndex: 1, batchSize: -1)
)
).data,
local!items: a!queryEntity(
entity: cons!PR_ITEM_ENTITY,
query: a!query(
pagingInfo: a!pagingInfo(startIndex: 1, batchSize: -1)
)
).data,
a!gridLayout(
headerCells: {
a!gridLayoutHeaderCell(label: "Summary"),
a!gridLayoutHeaderCell(label: "Qty", align: "RIGHT"),
a!gridLayoutHeaderCell(label: "Unit Price", align: "RIGHT"),
a!gridLayoutHeaderCell(label: "Total Price", align: "RIGHT")
},
columnConfigs: {
a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight: 4),
a!gridLayoutColumnConfig(width: "DISTRIBUTE"),
a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight: 2),
a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight: 2)
},
rowHeader: 1,
rows: a!forEach(
items: local!prs,
expression: a!localVariables(
local!expanded: false,
local!itemsForPr: index(
local!items,
/* Must cast to integer because a!queryEntity() returns a dictionary */
wherecontains(tointeger(fv!item.id), local!items.purchaseRequest.id),
{}
),
local!totalPrice: sum(
a!forEach(
items: local!itemsForPr,
expression:
tointeger(fv!item.qty) * todecimal(fv!item.unitPrice)
)
),
{
a!gridRowLayout(
contents: {
a!richTextDisplayField(
label: "Summary " & fv!index,
value: {
if(
length(local!itemsForPr)=0,
fv!item.summary,
a!richTextItem(
text: if(local!expanded, "-", "+") &" "& fv!item.summary,
link: a!dynamicLink(
value: not(local!expanded),
saveInto: local!expanded
)
)
)
}
),
a!textField(
label: "Qty " & fv!index,
readOnly: true
),
a!textField(
label: "Unit Price " & fv!index,
readOnly: true
),
a!textField(
label: "Total Price " & fv!index,
value: dollar(local!totalPrice),
readOnly: true,
align: "RIGHT"
)
}
),
if(
local!expanded,
a!forEach(
items: local!itemsForPr,
expression: a!gridRowLayout(contents: {
a!richTextDisplayField(
label: "Item Summary " & fv!index,
value: a!richTextBulletedList(
items: fv!item.summary
)
),
a!integerField(
label: "Item Qty " & fv!index,
value: fv!item.qty,
readOnly: true,
align: "RIGHT"
),
a!textField(
label: "Item Unit Price " & fv!index,
value: dollar(fv!item.unitPrice),
readOnly: true,
align: "RIGHT"
),
a!textField(
label: "Item Total Price " & fv!index,
value: dollar(tointeger(fv!item.qty) * todecimal(fv!item.unitPrice)),
readOnly: true,
align: "RIGHT"
)
})
),
{}
)
}
)
)
)
)
selection
parameter blank in our a!query()
function because we wanted to return all fields of the entities that we were querying.Expand/Collapse Rows in a Tree Grid