Dynamic Flex Configuration
 
Flex UI configuration supports capabilities which allow for dynamic construction of Flex UIs or more complex device responsiveness.
CALC: properties
Any property of any element can be specified as a string prefixed with CALC: in order to evaluate the following text as an expression and use the result as the value of the property. If any dynamic data referenced in the expression changes then the element will be regenerated with the updated property value, unless it is in the classes or styles sections, in which case it will simply dynamically update the class or style for the existing HTML element.
Apply the "nms-compact-headings" class to an element based on an expression
{
"id": "DYNAMIC_EXAMPLE",
"type": "panel",
"visible": "focusScorecardName() == 'LOADGEN'",
"classes": {
"nms-compact-headings": "CALC: loadGenOverviewMode()"
},
"children": [
...
]
}
Another common use for CALC in Flex is to do more complex device responsiveness, for example this switches a layout from using CSS flex row display to using column instead, if the containing tool is less than a certain width (xl in this case).
{
"id": "HEADER",
"type": "panel",
"layout": {
"type": "flex-row",
"styles": {
"flexWrap": "nowrap",
"gap": "CALC: sizeAtLeast('xl') ? '0px': '24px'",
"flexDirection": "CALC: sizeAtLeast('xl') ? 'row': 'column'"
}
}
}
The sizeAtLeast and corresponding sizeAtMost checks can be used in expressions to dynamically check against a number of predefined break points and apply different styles, classes or other element properties. The supported break points are:
 
sm / small
<= 600 pixels
md / medium
> 600 pixels
960px
> 960 pixels
lg / large
> 1000 pixels
1200px
> 1200 pixels
xl / extralarge
> 1400 pixels
Dynamic Map Styling Configuration
The CALC: syntax is also used extensively in the map configuration and there is additional information about that in that section.
If Then Else
The if element type allows a UI element to be included based on a condition, in the then property of the element, with an optional else property defining a UI element to be included if the condition evaluates to false. If anything changes in the data being tested against then the UI will be regenerated.
{
"type": "if",
"id": "EXAMPLE_IF",
"if": "exampleValue() === 'OPTION1'",
"then": {
... element definition
},
"else": {
... alternative element definition
}
}
Case
The case element type allows a UI element to be generated from a list of possibilities, either by comparing a value for each entry against a field or expression, or by each entry in the list having an expression to evaluate. A final entry with no value or if property can be provided as a default if none of the other entries in the list matched.
If anything changes in the data being tested against then the UI will be regenerated.
Using a fixed value expression
{
"type": "case",
"id": "EXAMPLE_CASE",
"field": "exampleSelection()",
"case": [
{
"value": 1,
"element": {
... element definition
}
},
{
"value": 2,
"element": {
... element definition
}
},
{
"element": {
... optional default if none of the above match
}
},
]
}
 
The same as the above but using an expression on each entry
{
"type": "case",
"id": "EXAMPLE_CASE",
"case": [
{
"if": "exampleSelection() == 1",
"element": {
... element definition
}
},
{
"if": "exampleSelection() == 2",
"element": {
... element definition
}
},
{
"element": {
... optional default if none of the above match
}
},
]
}
 
For Each
The for-each element type allows a UI element to be generated for each entry in a list, and if the list changes, the elements will be regenerated to match the new list. This requires some syntax to allow the referencing of data from the current list entry within the embedded element definition, so that each element generated from the list can be specific to its entry in the list. This relies on the CALC: syntax detailed earlier and by default you reference the item as $item. This can be overridden with configuration on the for-each element, for example if you had a nested for-each you would have to use a different name for the $item in the nested for-each.
Here is an example from the Update Multiple Events dialog configuration
{
id: 'COMPLETION_ACTION_FOREACH',
type: ElementType.ForEach,
field: 'picklistOptions',
template: [
{
id: 'COMPLETION_ACTION_IF_VISIBLE',
type: ElementType.If,
if: 'CALC: $item.visible',
then: {
id: 'CALC: $item.name + "_WRAPPER"',
type: ElementType.FlexBar,
layout: {
medium: 6,
large: 4
},
middleElement: {
id: 'CALC: $item.name',
field: '$item.value',
type: ElementType.SelectSingle,
removeUnselected: 'Unselected',
required: '$item.required',
label: 'CALC: $item.label',
options: '$item.entries',
enabled: '!$item.disabled()'
},
endElement: {
type: ElementType.CheckBox,
id: 'CALC: "CHK_" + $item.name',
ariaLabel: 'CALC: $item.label',
field: '$item.disabled',
trueValue: false,
falseValue: true
}
}
}
]
}