Tree

The Tree widget can be used to show hierarchical data in the form of nodes. Each node can have a sheer number of icons.

Model

{
    "type": "tree",
    "data": [
        {
            "n": "node-01",     // Shown as the label of the node
            "c": []             // Children
        }
    ],
    "schema": [],               // See Schema
    "schemaExtension": [],      // See Schema
    "searchTable": {}           // See Search Table
}

Drag-Drop

tree widgets, like all others, support drag-drop behavior when their dragSource and/or dropTarget properties in the model root are configured. While useful for dealing with the transfer of data relating to the widget as a whole, they are not convenient for managing drag-drop actions at node level.

These are configured by populating dragSource and/or dropTarget elements in the schema, either as direct child elements or in rules.

In the latter case, the behavior can be restricted to nodes in the tree which contain useful information to propagate, like object paths.

Refer to the schema and rules sections for more details. The rules declared in the options property also support drag-drop definitions.

With the initial release of the drag-drop feature, the message payload presented to the onDrop handler, doesn’t include any information of the node the drop relates to. As such, the main use of the feature at this stage is to support using tree nodes as drag sources rather than targets.

Schema

The schema element is optional. If it is omitted, the tree widget renders the data it receives hierarchically by inspecting each element and looking for a field called n, the value of which is shown as the node-text.

It then locates the c property which, if found, is expected to be an array of child nodes that can be recursively added to the display.

In order to support data with different fields, the defaults can be overridden by setting the name and children properties in the schema to point to custom fields in the node data.

In addition, the schema settings can be used to apply styles, add icons, tooltips and actions to the nodes in the tree.

{
    "schema": {
        "id": "i",                              // Default id field is 'i' or 'id'
        "name": "n",                            // Default name field is 'n'
        "children": "c",                        // Default children field is 'c'
        "icons": [                              // Generic for all nodes
            {
                "alignment": "leading",         // Default is 'leading'
                "position": 1,                  // Default index in the array + 1
                "icon": "ℹ️",
                "actions": {},
                "tooltip": {}                   // Icon tooltip to show
            },
            {
                "alignment": "leading",
                "position": 2,
                "icon": "❎",
                "actions": {}
            }
        ],
        "style": {                              // Node styling options
            "fontSize": "15px"
        },
        "tooltip" : {},                         // Default node tooltip
        "rules": [                              // Node specific icons, actions and styling
            {
                "match": {},                    // Match query
                "actions": {
                    "onClick": {}               // Node actions
                },
                "icons": [
                    {
                        "alignment": "leading",
                        "position": 2,
                        "icon": "🔍",
                        "actions": {}           // Action actions
                    }
                ],
                "style": {                      // Node styling options
                    "backgroundColor": "green",
                    "fontSize": "15px",
                    "fontWeight": "normal"
                },
                "tooltip": {}
            }
        ],
        "dragSource":{},                       // All tree nodes will serve as drag sources.
        "dropTarget":{}
    }
}
Field Description

children

Name of the field in the data which contains the child nodes of the current node. If the property is not provided the widget looks for a data field called c and interprets that as the array of child nodes.

dragSource
dropTarget

Configure all nodes in the tree to act as drag sources/drop targets.

When a dragSource is declared at schema level, all nodes in the tree will act as drag sources. The default message payload is initialized to the node data element including all its child nodes.

extendSchemaFromDataSource

This property is deprecated in favour of schemaExtension. By using these properties schema-settings from the widget model can be combined with those received from a dataSource. By default the schema in the model will take precedence over the schema received from the data source fetch.

By setting extendSchemaFromDataSource to "true" you can make use of both.

Typically the dataSource returns an object with both a data element and a schema element which defines the icons to use, whereas the model schema usually contains the node action definitions.

The extendSchemaFromDataSource property only applies to schema configuration which is defined in the model and should not be present in the schema from the dataSource.

Also refer to the data sources section for more detail.

icons

Optional array of icons to show with the node text (name). These icons will be applied to all nodes in the tree unless node-specific ones are defined using the rules property.

id

Name of the field in the data which uniquely identifies the tree node. If the property is not provided a field in the data called either i or id will be used as the node ID.

Having a unique node ID in the data is useful when using the search function. If one is not provided, the tree widget will generate a unique ID for each node based on its location in the data. (Refer to the state section for more information)

name

Name of the field in the data which will be used to show the node text/name. If the property is not provided, the tree widget looks for a field called n

style
styleByTheme

Use these properties to set the CSS style properties of the node. Typically the style property is used to declare all the theme independent properties. When theme specific dark or light styles are defined, these will be merged with the style settings, resulting in them taking precedence.

rules

This is an array property, each element of which defines a rule used to set node specific display attributes and/or behavior such as icons, tooltips and actions.

Refer to the rules section for more details.

tooltip

Set the default tooltip to show when the mouse cursor hovers over the node text.

schemaExtension

The schemaExtension property has the same structure as schema. It is intended to be used together with schema definitions received from a data sources which are assigned to the schema property.

In other words, the schemaExtension lets us configure common styling and rules for the tree, when additional configuration is to be provided from the system via a dataSource.

Icons

This property contains a list of one or more icons to display along side tree node text. It can be added in the schema section of the model as well as in rules, depending on whether they should be applied across the board or conditionally.

Each element in the array defines one icon, using the same common properties as described at widget level, but adds a number of tree widget specific ones as well.

{
    "icons": [
        {
            "actions": {},
            "alignment": "leading",
            "dark": {},
            "icon": {},
            "light": {},
            "position": 1,
            "tooltip": {}
        }
    ]
}
Field Description

actions

Actions to execute when the icon is clicked.

onClick

Action pipeline invoked when the icon is clicked. The payload field of the input message to the action pipeline contains the data of the selected tree node.

alignment

Indicates which side of the node text the icon should be drawn. Options are:

  • "leading": Icons are shown in front of the name text

  • "trailing": Icons are shown behind the name text.

Also refer to the position below.

dark
icon
light

Icons can be defined by:

Type Example

Emoji

"🌍"

URL to image

{ "url": "" }

Base64 encoded

{ "mimeType": "image/jpg", "base64": "" }

position

This is a number, starting at 1, which indicates where icons are shown relative to each other when there are more than one assigned to the node.

Nodes can have an arbitrary number of icons. By default the icons are positioned to the left of the node name. Icons can also be assigned on the right side of the node name.

Icon position numbering:

leading node label trailing

3 ← 2 ← 1

MyNode

1 → 2 → 3

Make sure to refer to the dataSource section if icons are provided dynamically.

tooltip

Set the tooltip to show when the mouse cursor hovers over this icon.

Rules

The rules element can be present in both the schema and the options section of the model. It contains an array of rule specifications, as shown below, which are evaluated against each node in the data.

When a data node matched the rule condition, the rule settings are applied to the node in the tree.

{
    "rules": [
        {
            "match": {},
            "actions": {},
            "icons": [],
            "style": {},
            "styleByTheme": {},
            "tooltip": {},
            "dragSource":{},
            "dropTarget":{}
        }
    ]
}
Field Description

actions

Actions to execute when the matching node is clicked.

dragSource
dropTarget

Drag-drop declarations made here restrict the behavior to nodes in the tree matching the current rule. These settings override those at schema level.

icons

Array of one or more icons to show in front of or after the matching nodes.

match

Condition used to determine which tree nodes the rule applies to. In the simplest case, the match condition consists of one or more node properties and the values they should have. If multiple properties are provided, all values have to match:

{
    "rules": [
        {
            "match": {
                "t": 520,
                "n" : "Planning department"
            }
        }
    ]
}

The node values can also be used in more complex mingo expressions such as:

{
    "rules": [
        {
            "match": {
                "t": {
                    "$gte": 550,
                    "$lt": 561
                },
                "n": "Planning department"
            }
        }
    ]
}

Even more complex match conditions can be built using the the mongoDB $expr operator. In the example below, the icon is applied to all nodes where: 550 \$<=\$ t \$<\$ 561 OR n starts with "Planning" :

{
    "rules": [
        {
            "match": {
                "$expr": {
                    "$or": [
                        {
                            "$and": [
                                {
                                    "$gte": [
                                        "$t",
                                        550
                                    ]
                                },
                                {
                                    "$lt": [
                                        "$t",
                                        561
                                    ]
                                }
                            ]
                        },
                        {
                            "$regexMatch": {
                                "input": "$n",
                                "regex": "^Planning"
                            }
                        }
                    ]
                }
            }
        }
    ]
}

style
styleByTheme

Set the CSS style properties of the node.

tooltip

Set the tooltip to show when the mouse cursor hovers over the icon.

Tooltip

This property can be used in the schema, rule and icon elements of the model.

{
    "tooltip": {
        "field": "n",
        "text": "Fallback",
        "type": "dynamic"
    }
}
Field Description

type

The tooltip type determines where the displayed text is sourced from. The options are:

  • "fixed": The tooltip text will be taken from the text field of the tooltip element

  • "dynamic": The tooltip text is taken from a field in the data of the node where the mouse cursor is hovering. The tooltip.field property defines the name of the data field to use.

text

Text used for the tooltip when the type is set to "fixed" or when the "dynamic" field is not found in the data node.

field

Name of the field in the data node used as the tooltip text. If the field is not a string, an attempt will be made to convert it to one. Composite fields have no default conversion to a string representation.

Options

Node styling and icon assignment can be combined using the rules in the options. The configuration in the schema takes precedence over settings in the options section.

{
    "options": {
        "rules": [
            {
                "match": {},
                "icons": [                      // List of icon definition
                    {
                        "icon": "ℹ️",
                        "actions": {}           // See Actions
                    },
                    {
                        "icon": "👁",
                        "actions": {}           // See Actions
                    }
                ],
                "style": {
                    "backgroundColor": "green",
                    "fontSize": "15px",
                    "fontWeight": "normal"
                }
            },
            {
                "match": {},
                "icons": [                      // List of icon definition
                    {
                        "alignment": "trailing",
                        "position": 1,
                        "icon": "🌍",
                        "actions": {}           // See Actions
                    }
                ],
                "style": {
                    "fontWeight": "bold"
                }
            }
        ]
    }
}
name description

allowSearch

Shows the magnify glass button in the toolbar (default is true).

collapseOnSearchSelection

The tree will be collapsed when a selection is made in the search table.

showRefreshButton

Shows the refresh button in the toolbar (default is true).

State

The tree widget maintains a list of expanded nodes by recording their "identifier" fields in the state.expandedNodes array.

{
    "state": {
        "expandedNodes": [ "1", "1.2" ]
    }
}

The "identifier" defaults to the provided schema id field (which must be unique in the tree). If an id is not provided, one will be automatically generated by encoding the index of the node at each level in the tree. For example, the second child node of the first root element would get id = "1.2"

In addition to tracking the expandedNodes state, the widget also uses this information to restore the tree to the same state when a reload is triggered.

Note: When the reload is due to new data being fetched, the tree state can only be reliably restored if the node ids before and after the load are the same. This is not guaranteed when using "automatic" id generation since these are base on the position of the nodes in the tree which may change due to inserts or deletions. The recommendation is therefor to explicitly provide unique node ids whenever possible.

The expandedNodes property can also be modified from an action pipeline to manipulate the tree’s appearance.

Note: The whole expandedNodes array must be changed when doing so. Individual elements in the array cannot be changed.

By way of example, suppose we have the following tree and want to expand it such that the "Machine X" node is visible.

Id      Name
------- -------------------
1       Site 1
        |
1.1     +- Area A
        |  |
1.1.1   |  +- Line 1A
        |
1.2     +- Area B
           |
1.2.1      +- Line 1B
           |  |
1.2.1.1    |  +- Machine X
           |
1.2.2      +- Line 2B

To do so, all parent nodes of "1.2.1.1" need to be put into the expandedNodes array, not just its immediate parent node:

{
    "type": "modify",
    "id": "tree",
    "set": [
        {
            "name": "model.state.expandedNodes",
            "value": [ "1", "1.2", "1.2.1" ]
        }
    ]
}

Search Table State

In addition to the state property, there is also a searchTable.state property which keeps track of active row selection, filter and search options of the tree search table. Refer to the search table section more details.

Data Sources

A dataSource can be defined in the widget model to fetch data from the system. How the data returned from the dataSource is interpreted, depends on its structure as follows:

  • Array: The array is assumed to be data and is applied to the widget’s data property.

  • Object : The object is inspected, looking for properties called data and schema. The message data is applied to the model data field. The schema property from the dataSource is handled according the the table below:

    The model contains a schema field The extend SchemaFrom DataSource property is set to "true" The model schema Extension section is defined. Merge behavior

    No

    No

    The schema from the dataSource is applied to the work model schema.

    No

    Yes

    The schema from the dataSource is applied to the work model schema. The schemaExtension in the model is left in place and the settings interpreted together with the ones in the model schema.

    Yes

    No

    No

    The schema from the dataSource is ignored.

    Yes

    No

    Yes

    The schema from the dataSource is ignored. The model schema and schemaExtension are interpreted together

    Yes

    Yes

    No

    The schema in the model is re-assigned to the model.schemaExtension and the one from the dataSource is assigned to the model.schema

    Yes

    Yes

    Yes

    The schema in the model is overwritten by the one from the data source and and the schemaExtension remains in place.

Icon definitions dynamically applied by the dataSource can only be merged with those in the static model, provided their positions don’t overlap. That is to say, each icon applied to a node in the tree must have a specific, non-overlapping position in front of or behind the node text.

Actions

Nodes and icons of nodes support action hooks. An action hook supports the standard action pipeline. The message payload is the data of the node.

Supported action hooks:

  • onClick: when user clicks on the node or on one of its icons.

  • onSelect: triggers with onClick or when a node is selected using the search table.

  • onSelectionChanged: triggers when the selection is changed. That is to say, it is only triggered the first time if the same node is selected multiple times in succession.

Generic onClick action hook for a node:

    {
        "actions": {
            "onClick": {
                "type": "send",
                "to": "debugger"
            }
        }
    }

Generic onClick action hook for a node icon:

{
    "icons": [
        {
            "icon": "ℹ️",               // Only applies when there is no matching rule.
            "actions": {
                "onClick": {
                    "type": "send",
                    "to": "debugger"
                }
            }
        }
    ]
}

A specific action can be configured within the rules. These are dominant to the generic actions.

Action on a specific icon:

{
    "icons": [
        {
            "icon": "ℹ️",               // Only applies when there is no matching rule.
            "rules": [
                {
                    "match": {
                        "t": 1034       // Type in the form of the class number
                    },
                    "icon": "🍺",
                    "actions": {
                        "onClick": {
                            "type": "send",
                            "to": "debugger"
                        }
                    }
                }
            ]
        }
    ]
}

Search Table

Tree data can be searched by clicking on the magnifying glass in the toolbar. By default, a search table is shown containing the names and hierarchies of all the tree nodes. Searches are performed against the text shown in the table.

To allow any field in the tree data to be searched the searchTable, which is a regular Table widget, must be explicitly defined in the widget model. Each added column is automatically included in the search.

Currently only captionBar, schema, options and state are supported in the searchTable model.
{
    "searchTable": {
        "captionBar": {
            "title": "Tree Search",
            "showModelEditorButton": false,
            "style": {
                "border": "2px solid white"
            }
        },
        "schema": [
            {
                "name": "nodeName",
                "title": "Name",
                "sort": "asc"
            },
            {
                "name": "text",
                "title": "Description"
            },
            {
                "name": "_hierarchy",
                "title": "Hierarchy"
            }
        ],
        "options": {
            "pagination": false
        },
        "state": {
            "filters": [],
            "search": {
                "value": ""
            }
        }
    }
}

Some additional points to consider:

  • Use the`captionBar` property to customize or hide the caption bar. Refer to the generic Widget for further details

  • The _hierachy field is created by the tree widget and made available for inclusion in the custom search table schema.

  • Deep linking of node properties is not supported.

    {
        "searchTable": {
            "schema": [
                {
                    "name": "props.name",       // NOT SUPPORTED
                    "title": "Name",
                }
            ]
        }
    }