Pointers and Contexts
BizzStream expressions use pointers to reference specific field values or line-level values within documents, similar to cell references in spreadsheets. In this article, we'll explore the concept of pointers and how they work in BizzStream expressions.
Let's explore how pointers work using the following timesheets document:
{
"name": "Joe Smith",
"approvalDate": "2023-05-01",
"totalHours": 15,
"equipmentId": "67ae05cfd2938baf6ebf4941",
"timesheets": [
{
"_id": "a9ac590a-cb64-4186-9c92-a0317bb7a36b",
"date": "2022-04-22",
"hours": 5
},
{
"_id": "f8bc3cff-a492-4e9e-8d6c-e51497fd0461",
"date": "2022-04-23",
"hours": 10
}
],
"remarks": [
{
"_id": "57145777-bc4a-45a9-a818-49d525e9d720",
"authorId": "73a3e8b1-9e74-4b9c-a271-f960b0e932e4",
"remark": "Just a normal day"
}
]
}
Pointers
Pointer Type | Syntax Example | Description |
---|---|---|
Field Pointer | F["name"] |
Accesses a specific field in a document. |
Reference Field Pointer | REF["equipmentId"].F["name"] |
Accesses a field in a referenced document. |
All Lines Pointer | L["timesheets"][*] |
Retrieves all lines from a Line Block. |
Single Line Pointer | L["timesheets"][0] |
Retrieves a specific line (zero-based index). |
Line Field Pointer | L["timesheets"][*].F["hours"] |
Retrieves a specific field from all lines. |
Source Line Field Pointer | SRL.F["hours"] |
Retrieves a field from the current line. |
Control Pointer | CTRL["timesheetsGrid"] |
Refers to a control in a layout. |
Layout Pointer | LAY["name"] |
Accesses a layout. |
Dataset Pointer | DS["datasetInOverlayLayout"] |
Accesses a dataset in an overlay target layout. |
Overlay Layout Target Pointer | OVRLTGT.DS["datasetInOverlayLayout"] |
Accesses a dataset in an overlay target layout. |
Overlay Layout Source Pointer | OVRLSRC.DS["datasetInSourceLayout"] |
Accesses a dataset in an overlay target layout. |
Field Pointer
When you want to get the value of the field "name" in a document, you should use the pointer:
F["name"]
Given the timeheet example document, this expression resolves to "Joe Smith".
In order to get the value of a reference field, the pointer to use is different, because you need to reference a value in the reference document:
REF["equipmentId"].F["name"]
The first part REF["equipmentId"]
points to the reference field. The second
part, .F["name"]
points to the "name" field in the reference document.
All Lines Pointer
To refer to all the "timesheets" lines in a document, you should use the following pointer:
L["timesheets"][*]
This returns an array of all lines including all fields, in this case
[
{
"_id": "a9ac590a-cb64-4186-9c92-a0317bb7a36b",
"date": "2022-04-22",
"hours": 5
},
{
"_id": "f8bc3cff-a492-4e9e-8d6c-e51497fd0461",
"date": "2022-04-23",
"hours": 10
}
]
Single Line Pointer
When you want to refer to a specific "timesheets" line in a document, you should use the pointer:
L["timesheets"][0]
Here, the number enclosed by the square brackets is the index of the line in the array. This index is zero-based, which means that the first element has index 0. When such an expression is resolved, it will return the content of the line, in this case:
{
"_id": "a9ac590a-cb64-4186-9c92-a0317bb7a36b",
"date": "2022-04-22",
"hours": 5
}
Line Field Pointer
When you want to refer to a field in all lines, you can use the following pointer:
L["timesheets"][*].F["hours"]
This will return an array of the hour values, in this case [ 5, 10 ]
.
Source Line Field Pointer
If you are in a document line in a Document Dataset, and want to refer to a field within the same line, you can use this pointer:
SRL.F["hours"]
Thus, when the following expression is resolved for the first "timesheets" line in the example document, it yields 5. When it is resolved for the second line, it yields 10.
Field Pointer in Filter Datasets
In filter datasets, pointers will resolve to an array, instead of a single value. This way it accomodates for the fact that a Between Filter uses two values. In order to access data from a Filter Dataset field you may use the BizzStream expressions similar to field pointers. Let's try and access a "startDate" filter field:
F["startDate"]
The result is an array where index 0 holds the first filter value
(filterValue1
), and index 1 holds the second value (filterValue2
), if
applicable. If the filter operator is between
, filterValue2
will be
populated; otherwise, it remains undefined
.
So F["startDate"]
resolves in the context of a filter dataset to
["2024-07-05", "2024-07-08"]
.
To access only "filterValue1" you may use this pointer in combination with the INDEX operator.
INDEX(F["startDate"], 0)
This will result in the string "2024-07-05".
Control Pointer
When you want to point to control in a layout, you can use the control pointer.
For example, the pointer CTRL["timesheetsGrid"]
refers to a control with the
name "timesheetsGrid". Control pointers can only be used in combination with the
SELECTED and
CHECKED control operators.
The special control pointer CTRL["treeview"]
will point to the treeview
control. With the SELECTED you use it to
find which item is selected. SELECTED(CTRL["treeview"], "name")
will get the
name of the selected item.
Layout Pointer
To point to a layout, you may use a Layout pointer. This pointer can be used to
point to fields in
different layouts. For example LAY["name"].DS["test"].F["name"]
points to
field "name" in the dataset "test" in the layout "name".
Layout pointers can also be used in combination with the ISOVERLAYLAYOUT operator to verify that a layout is used for the purpose of an overlay layout.
ISOVERLAYLAYOUT(LAY["ordersOverview"])
Dataset Pointer
You can point to a dataset by using a dataset pointer like DS["test"]
. In a
single item dataset it will resolve to the document. This means that you can
access fields directly with DS["test"].F["fieldName"]
. In a list dataset, the
dataset will resolve to all documents. You have to use an index to access a
single document, or use the asterisk to access all documents:
DS["test"][*].F["fieldName""]
.
In overlay layouts, pointers can be used to define whether a dataset can be found in the overlay layout or in the source layout.
OVRLTGT.DS["datasetInOverlayLayout"]
OVRLSRC.DS["datasetInSourceLayout"]
Pointers that Cannot be Resolved
In some cases, BizzStream cannot resolve a pointer, for instance because a
field does not exist. In that case, the expression will yield the undefined
value.
Contexts
When a BizzStream expression is calculated, its context is taken into account. The context of a BizzStream expression determines which document(s) or layouts it applies to, based on where the expression is used.
Document Definition
BizzStream expressions that are used in a document definition are resolved in the context of the document. For instance, the BizzStream expression used to determine whether the Terminate rule should be triggered, uses the document that the action processes as context.
Layouts
When BizzStream calculates expressions in layouts, it needs to know exactly which dataset to use. If you need to reference to a dataset outside the scope of the current layout, you have to provide additional context. The context that BizzStream needs, consists thus of two elements:
- The name of the menu block that renders a layout.
- The name of the dataset within the menu block.
This information can be provided by prefixing the pointers. For instance, the
BizzStream expression M["timesheetDetails"].DS["timesheet"].F["name"]
resolves to the "name" field (F["name"]
) in the "timesheet" dataset
(DS["timesheet"]
) in the "timesheetDetails" menu block
(M["timesheetDetails"]
).
Multiple contexts can be used within a single BizzStream expression. For
example, the expression
M["clientDetails"].DS["clientInfo"].F["totalRevenue"] + M["orderDetails"].DS["orderInfo"].F["totalRevenue"]
adds the value of the "totalRevenue" field within the "clientInfo" dataset in
the "clientDetails" menu block to the "totalRevenue" field within the
"orderInfo" dataset in the "orderDetails" menu block.
Controls Linked to a Dataset
In many cases, expressions that are used in controls linked to a dataset should be resolved in the context of that same dataset. In that case, it is not necessary to extend the pointer with information about the dataset and menu block.
For example, suppose we have a layout with a Document Dataset containing a timesheet. We can configure an expression to disable a control in the layout if the field approvalDate has a certain value. If that control is linked to the same dataset as the approvalDate field, the dataset pointer is not required. These two expressions are equivalent:
F["approvalDate"] > "2022-05-10"
M["timesheetDetails"].DS["timesheet"].F["approvalDate"] > "2022-05-10"
The first version is preferred for readability.
Same layout, Different Dataset
Likewise, if you want to resolve a BizzStream expression in the context of
another dataset in the same layout, it suffices to extend the pointer with a
dataset context. For example, DS["approverInformation"].F["name"]
is the same
as M["timesheetDetails"].DS["approverInformation"].F["name"]
.
Control Pointers and Context
Because control names should be unique within a layout, control pointers can only be extended with menu block information:
M["timesheetDetails"].CTRL["timesheetsGrid"]
Again, it is not necessary to provide menu block information if the control resides in the same menu block.
O
(Object) Operator
The O
operator is used to reference and manipulate fields within a document.
Syntax
O[pointer]
Parameters:
- pointer: A reference to the desired field within the document.
Examples
- O["coordinates"].F["formattedAddress"]: This retrieves the
formattedAddress
field from thecoordinates
object, typically representing a geolocation field.
Menus
Pointers in BizzStream expressions used to determine whether path from one menu block to another should be followed, the path conditions, are always resolved in the context of the menu block layout. This implies that it suffices to extend the pointer with a dataset prefix.
However, if you want to use a dataset in another menu block, you should extend the pointer with a menu block prefix.