# 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
"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
{
"position": 1,                  // Default index in the array + 1
"icon": "ℹ️",
"actions": {},
"tooltip": {}                   // Icon tooltip to show
},
{
"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": [
{
"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`

The `schema` in the model will overrule 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.

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.

## 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": {},
"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:

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 table state property for 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`. If a `schema` property is found and there is no schema at root level in the model, the supplied one is used. Otherwise, the rules in the return `schema` element are combined with the ones already present in the model, provided the `extendSchemaFromDataSource` property is set to true.

 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 icon of nodes support action hooks. An action hook supports the standard action pipeline. The message payload is de 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

In order to show the proper and desired node fields in search table, a `searchTable` configuration can be made. The prompted search table is a Table widget. Currently only `schema` and `options` are supported.

``````{
"searchTable": {
"schema": [
{
"name": "nodeName",
"title": "Name",
"sort": "asc"
},
{
"name": "text",
"title": "Description"
},
{
"name": "path",
"title": "Path"
}
]
}
}``````

Note: deep linking of node properties is not supported.

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