Help with nested data on tables

Hello everyone, i'm kinda new on node-red, javascript and i read about how the ui-table is able to do nested data (because it uses tabulator under the hood) but i can't find any example of how to specifically do it.

I'm running this system:

  • Node-RED version: v4.0.2
  • Node.js version: v20.15.0
  • Dashboard version 3.6.5
[
    {
        "name": "root_1a_node",
        "browsename": "s=0;ns=0",
        "children": [
            {
                "name": "root_2a_leaf",
                "browsename": "s=1;ns=0",
                "children": null
            },
            {
                "name": "root_2b_node",
                "browsename": "s=1;ns=1",
                "children": [
                    {
                        "name": "root_3a_leaf",
                        "browsename": "s=2;ns=0",
                        "children": null
                    },
                    {
                        "name": "root_3b_node",
                        "browsename": "s=2;ns=1",
                        "children": null
                    }
                ]
            }
        ]
    },
    {
        "name": "root_1b_node",
        "browsename": "s=0;ns=1",
        "children": [
            {
                "name": "root_2c_leaf",
                "browsename": "s=1;ns=2",
                "children": null
            }
        ]
    },
    {
        "name": "root_1c_node",
        "browsename": "s=0;ns=2",
        "children": [
            {
                "name": "root_2d_leaf",
                "browsename": "s=1;ns=3",
                "children": null
            },
            {
                "name": "root_2e_node",
                "browsename": "s=1;ns=4",
                "children": [
                    {
                        "name": "root_3c_leaf",
                        "browsename": "s=2;ns=2",
                        "children": null
                    },
                    {
                        "name": "root_3d_node",
                        "browsename": "s=2;ns=3",
                        "children": null
                    }
                ]
            }]
    }
    {
        "name": "root_1d_leaf",
        "browsename": "s=0;ns=3",
        "children": null
    }
]

And using this example to read it a json file and insert it into a table i only get the ones at the top level:

[
    {
        "id": "5f64b8cf257213d8",
        "type": "tab",
        "label": "Flow 5",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "97e6193c4a7496e7",
        "type": "ui_template",
        "z": "5f64b8cf257213d8",
        "group": "0f5aa10037de10f6",
        "name": "",
        "order": 1,
        "width": 0,
        "height": 0,
        "format": "<div>\n    <table>\n        <thead>\n            <tr>\n                <th>Groep</th>\n                <th>Naam</th>\n                <th>Omschrijving</th>\n                <th>Model</th>\n                <th>Adres</th>\n            </tr>\n        </thead>\n        <tbody>\n            <tr ng-repeat-start=\"obj in msg.payload\">\n                <td colspan=\"4\">{{ obj.group_name }}</td>\n            </tr>\n            <tr ng-repeat=\"device in obj.device_list\">\n                <td>&nbsp;</td>\n                <td>{{ device.device_name }}</td>\n                <td>{{ device.omschrijving }}</td>\n                <td>{{ device.model }}</td>\n                <td>{{ device.address }}</td>\n            </tr>\n            <tr ng-repeat-end>\n                <td colspan=\"4\">&nbsp;</td>\n            </tr>\n        </tbody>\n    </table>\n</div>",
        "storeOutMessages": true,
        "fwdInMessages": true,
        "resendOnRefresh": true,
        "templateScope": "local",
        "className": "",
        "x": 846.4409732818604,
        "y": 433.15281105041504,
        "wires": [
            []
        ],
        "l": false
    },
    {
        "id": "e1e6571ce4d8ab18",
        "type": "inject",
        "z": "5f64b8cf257213d8",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "[{\"group_name\":\"White_Group\",\"device_list\":[{\"device_name\":\"dev1\",\"group_name\":\"White_Group\",\"omschrijving\":\"A device\",\"model\":\"LED123\",\"address\":\"0xAAAAAAA\"},{\"device_name\":\"dev2\",\"group_name\":\"White_Group\",\"omschrijving\":\"Another device\",\"model\":\"LED456\",\"address\":\"0xBBBBBB\"}]},{\"group_name\":\"Green_Group\",\"device_list\":[{\"device_name\":\"dev3\",\"group_name\":\"Green_Group\",\"omschrijving\":\"Device #3\",\"model\":\"LED5678\",\"address\":\"0xCCCCC\"},{\"device_name\":\"dev4\",\"group_name\":\"Green_Group\",\"omschrijving\":\"Device #4\",\"model\":\"LED9012\",\"address\":\"0xDDDDDD\"}]}]",
        "payloadType": "json",
        "x": 460.44447326660156,
        "y": 440.2361225097656,
        "wires": [
            [
                "97e6193c4a7496e7"
            ]
        ],
        "l": false
    },
    {
        "id": "7d8fe878372a6289",
        "type": "inject",
        "z": "5f64b8cf257213d8",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 422.4409942626953,
        "y": 329.2291645019531,
        "wires": [
            [
                "0efb12f81f07a6e6"
            ]
        ],
        "l": false
    },
    {
        "id": "0efb12f81f07a6e6",
        "type": "file in",
        "z": "5f64b8cf257213d8",
        "name": "",
        "filename": "\\Users\\Eduardo\\Documents\\Node-Red\\telegram.json",
        "filenameType": "str",
        "format": "utf8",
        "chunk": false,
        "sendError": false,
        "encoding": "none",
        "allProps": false,
        "x": 570.4444732666016,
        "y": 326.67710151367186,
        "wires": [
            [
                "d64875f95d64a746"
            ]
        ],
        "l": false
    },
    {
        "id": "d64875f95d64a746",
        "type": "json",
        "z": "5f64b8cf257213d8",
        "name": "",
        "property": "payload",
        "action": "",
        "pretty": false,
        "x": 738.4479522705078,
        "y": 328.77777900390623,
        "wires": [
            [
                "cfd1594c150ca0e9",
                "3edc870a73456c57"
            ]
        ],
        "l": false
    },
    {
        "id": "cfd1594c150ca0e9",
        "type": "ui_table",
        "z": "5f64b8cf257213d8",
        "group": "462799bd91b3bec6",
        "name": "",
        "order": 2,
        "width": 0,
        "height": 0,
        "columns": [
            {
                "field": "name",
                "title": "Node Name",
                "width": "",
                "align": "left",
                "formatter": "plaintext",
                "formatterParams": {
                    "target": "_blank"
                }
            },
            {
                "field": "browsename",
                "title": "Browse Name",
                "width": "",
                "align": "left",
                "formatter": "plaintext",
                "formatterParams": {
                    "target": "_blank"
                }
            }
        ],
        "outputs": 1,
        "cts": true,
        "x": 938.4479522705078,
        "y": 332.3541645019531,
        "wires": [
            [
                "0becf574c9451181",
                "8b2eddc405e0a58d"
            ]
        ],
        "l": false
    },
    {
        "id": "3edc870a73456c57",
        "type": "debug",
        "z": "5f64b8cf257213d8",
        "name": "debug 7",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 797.8958129882812,
        "y": 222.90277099609375,
        "wires": [],
        "l": false
    },
    {
        "id": "0becf574c9451181",
        "type": "debug",
        "z": "5f64b8cf257213d8",
        "name": "debug 8",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 1037.8957586288452,
        "y": 266.9027786254883,
        "wires": [],
        "l": false
    },
    {
        "id": "8b2eddc405e0a58d",
        "type": "ui_toast",
        "z": "5f64b8cf257213d8",
        "position": "dialog",
        "displayTime": "3",
        "highlight": "",
        "sendall": false,
        "outputs": 1,
        "ok": "OK",
        "cancel": "Cancel",
        "raw": false,
        "className": "",
        "topic": "msg.payload",
        "name": "",
        "x": 1156.4514923095703,
        "y": 337.9618,
        "wires": [
            []
        ],
        "l": false
    },
    {
        "id": "0f5aa10037de10f6",
        "type": "ui_group",
        "name": "table-handler-demo #1",
        "tab": "e1379137854c8e35",
        "order": 2,
        "disp": true,
        "width": "9",
        "collapse": true
    },
    {
        "id": "462799bd91b3bec6",
        "type": "ui_group",
        "name": "Table with nested Data",
        "tab": "a0e8e0650dd65076",
        "order": 1,
        "disp": true,
        "width": "12",
        "collapse": false,
        "className": ""
    },
    {
        "id": "e1379137854c8e35",
        "type": "ui_tab",
        "name": "ui-table",
        "icon": "dashboard",
        "order": 6,
        "disabled": false,
        "hidden": false
    },
    {
        "id": "a0e8e0650dd65076",
        "type": "ui_tab",
        "name": "Table Test",
        "icon": "dashboard",
        "disabled": false,
        "hidden": false
    }
]

image

I could have all of the nodes at the same level and add a parameter to indicate its parent but i want to make the parent to be able to show or hide its children.

If anyone is interested, the idea is to read and OPC server, get all the nodes and add a context menu to subscribe/unsuscribe/etc, keeping the table dynamically updated.

You will probably see me around here as i am also developing a calendar page for keeping track of night duties, a notification system connected to the calendar that will notify those on duty via telelgram or email and a telegram bot to keep track of the OPC nodes subscribe to, events and alarms.

If you send

{
    "ui_control": {
         "tabulator": {
             "dataTree":true
          }
    }
}

As well as columns and use "_children"
then the table will show nested data.
You can also specify a children property using "dataTreeChildField":"children",
Read about all config for tree here Tabulator | JavaScript Tables & Data Grids
ui-table use tabulator 4.* so make sure you use older documentation.
example flow

[{"id":"7d8fe878372a6289","type":"inject","z":"5f64b8cf257213d8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"[{\"name\":\"root_1a_node\",\"browsename\":\"s=0;ns=0\",\"_children\":[{\"name\":\"root_2a_leaf\",\"browsename\":\"s=1;ns=0\",\"_children\":null},{\"name\":\"root_2b_node\",\"browsename\":\"s=1;ns=1\",\"_children\":[{\"name\":\"root_3a_leaf\",\"browsename\":\"s=2;ns=0\",\"_children\":null},{\"name\":\"root_3b_node\",\"browsename\":\"s=2;ns=1\",\"_children\":null}]}]},{\"name\":\"root_1b_node\",\"browsename\":\"s=0;ns=1\",\"_children\":[{\"name\":\"root_2c_leaf\",\"browsename\":\"s=1;ns=2\",\"_children\":null}]},{\"name\":\"root_1c_node\",\"browsename\":\"s=0;ns=2\",\"_children\":[{\"name\":\"root_2d_leaf\",\"browsename\":\"s=1;ns=3\",\"_children\":null},{\"name\":\"root_2e_node\",\"browsename\":\"s=1;ns=4\",\"_children\":[{\"name\":\"root_3c_leaf\",\"browsename\":\"s=2;ns=2\",\"_children\":null},{\"name\":\"root_3d_node\",\"browsename\":\"s=2;ns=3\",\"_children\":null}]}]},{\"name\":\"root_1d_leaf\",\"browsename\":\"s=0;ns=3\",\"_children\":null}]","payloadType":"json","x":422.4409942626953,"y":329.2291645019531,"wires":[["3edc870a73456c57","8115c722.5d91d8"]],"l":false},{"id":"3edc870a73456c57","type":"debug","z":"5f64b8cf257213d8","name":"debug 7","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":797.8958129882812,"y":222.90277099609375,"wires":[],"l":false},{"id":"8115c722.5d91d8","type":"change","z":"5f64b8cf257213d8","name":"ui_control","rules":[{"t":"set","p":"ui_control","pt":"msg","to":"{\"tabulator\":{\"dataTree\":true,\"columns\":[{\"title\":\"Node Name\",\"field\":\"name\"},{\"title\":\"Browse Name\",\"field\":\"browsename\"}]}}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":600,"y":320,"wires":[["c987587d20fd7989"]]},{"id":"c987587d20fd7989","type":"ui_table","z":"5f64b8cf257213d8","group":"462799bd91b3bec6","name":"","order":2,"width":"12","height":"10","columns":[],"outputs":1,"cts":true,"x":725,"y":320,"wires":[[]],"l":false},{"id":"462799bd91b3bec6","type":"ui_group","name":"Table with nested Data","tab":"a0e8e0650dd65076","order":1,"disp":true,"width":"12","collapse":false,"className":""},{"id":"a0e8e0650dd65076","type":"ui_tab","name":"Table Test","icon":"dashboard","disabled":false,"hidden":false}]

I understand you are using ui-table on Dashboard-1.0 which has been announced as end-of-life. I recommend that you try @omrid01/node-red-dashboard-2-table-tabulator, which runs on dashboard-2.0, uses the latest Tabulator version and has much broader functionality, as well as documentation & examples.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.