I am using tabulator.js in a ui-template. This works perfectly in my example flow.
[
{
"id": "a361f3170fba9d32",
"type": "ui_template",
"z": "b5632267ab948d52",
"group": "87e32ce83242e0f3",
"name": "tabulator.js html/scr/css ",
"order": 1,
"width": 0,
"height": 0,
"format": "<link href=\"https://unpkg.com/tabulator-tables@5.4/dist/css/tabulator.min.css\" rel=\"stylesheet\">\n<script type=\"text/javascript\" src=\"https://unpkg.com/tabulator-tables@5.4/dist/js/tabulator.min.js\"></script>\n\n<!-- see http://tabulator.info/examples/5.4#theming \ndark: /dist/css/tabulator_midnight.min.css\nadjustable: /dist/css/tabulator.min.css\n//-->\n\n<div id=\"openWindowsTable\"></div>\n<script>\n var table = new Tabulator(\"#openWindowsTable\", {\n height:\"700px\" ,\n placeholder:\"Keine Daten verfügbar!\",\n layout: \"fitDataStretch\",\n \n movableColumns: true,\n /*allow column order to be changed*/\n \n /*colums format definitions*/\n columns: [{\n title: \"Fenster\",\n field: \"window\",\n width: 250\n },\n {\n title: \"Status\",\n field: \"status\",\n formatter: function(cell, formatterParams, onRendered){\n //cell - the cell component\n //formatterParams - parameters set for the column\n //onRendered - function to call when the formatter has been rendered\n return \"<span style='color:Black; font-weight:bold;'>\" + cell.getValue() + \"</span>\"\n },\n },\n {\n title: \"Zeit\",\n field: \"ts\",\n },\n ],\n \n columnDefaults:{ \n tooltip:true,\n },\n \n /*initial sorting */\n initialSort:[\n {column:\"status\", dir:\"desc\"}, //sort by this first\n {column:\"ts\", dir:\"desc\"}, //then sort by this second\n ],\n \n /* group by ort*/\n groupBy: \"ort\",\n groupStartOpen: true,\n\n /* format groupHeader */\n groupHeader: function(value, count, data, group) {\n var r = \"<span style='color:#d00; margin-left:10px;'>(\" + count + \" Fenster)</span>\";\n return value + r;\n },\n \n /*format individal cell*/\n rowFormatter: function(row) {\n const cl = row.getCells();\n cl[1].getElement().style.backgroundColor = (cl[1]._cell.value === 'open' ? '#F1948A' : '#82E0AA');\n },\n });\n\n /* events */\n \n table.on(\"renderComplete\",function() {\n let data = table.getData();\n let groupHeaderList = document.querySelectorAll(\".tabulator-row.tabulator-group\");\n let groups = Array.from(groupHeaderList, (group) => group.outerText.split('(')[0]);\n \n for (let i = 0; i < groups.length; i++) { const group=groups[i]; const statusOpen=data.some(g=> g.ort === group &&\n g.status === 'open');\n groupHeaderList[i].style.backgroundColor = (statusOpen) ? '#E74C3C' : '#2ECC71';\n }\n });\n\n \n table.on(\"tableBuilt\", function() {return console.log(\"from tableBuilt event\")});\n \n (function(scope) { \n scope.$watch('msg', function(msg) {\n if(msg) {\n var tabledata = msg.payload;\n table.replaceData(tabledata);\n \n }\n });\n })(scope);\n\n</script>",
"storeOutMessages": true,
"fwdInMessages": true,
"resendOnRefresh": true,
"templateScope": "local",
"className": "",
"x": 650,
"y": 400,
"wires": [
[]
]
},
{
"id": "6974f7f03a30f5fb",
"type": "inject",
"z": "b5632267ab948d52",
"name": "Testdata",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "[\t {\t \"window\":\"Zwischentür_vorn\",\t \"status\":\"closed\",\t \"ts\":\"09.10.22 07:26:37\",\t \"ort\":\"Aussen\"\t },\t {\t \"window\":\"Zwischentür_Hof\",\t \"status\":\"closed\",\t \"ts\":\"09.10.22 07:26:36\",\t \"ort\":\"Aussen\"\t },\t {\t \"window\":\"Haustür\",\t \"status\":\"closed\",\t \"ts\":\"09.10.22 09:22:11\",\t \"ort\":\"EG\"\t },\t {\t \"window\":\"WG_Fenster_links\",\t \"status\":\"closed\",\t \"ts\":\"09.10.22 09:22:06\",\t \"ort\":\"EG\"\t },\t {\t \"window\":\"Büro_WGn\",\t \"status\":\"closed\",\t \"ts\":\"09.10.22 07:28:52\",\t \"ort\":\"EG\"\t },\t {\t \"window\":\"Fenster_Gäste_WC\",\t \"status\":\"closed\",\t \"ts\":\"09.10.22 06:53:09\",\t \"ort\":\"EG\"\t },\t {\t \"window\":\"WG_Schiebetuer\",\t \"status\":\"closed\",\t \"ts\":\"09.10.22 06:48:47\",\t \"ort\":\"EG\"\t },\t {\t \"window\":\"WGTuer\",\t \"status\":\"closed\",\t \"ts\":\"09.10.22 06:48:25\",\t \"ort\":\"EG\"\t },\t {\t \"window\":\"WG_Fenster_rechts\",\t \"status\":\"closed\",\t \"ts\":\"09.10.22 06:33:56\",\t \"ort\":\"EG\"\t },\t {\t \"window\":\"Wirtschaftsraum_Fenster\",\t \"status\":\"closed\",\t \"ts\":\"03.10.22 02:04:44\",\t \"ort\":\"EG\"\t },\t {\t \"window\":\"Kellerküche_Fenster\",\t \"status\":\"open\",\t \"ts\":\"30.09.22 11:16:50\",\t \"ort\":\"Keller\"\t },\t {\t \"window\":\"Sportraum_Fenster\",\t \"status\":\"closed\",\t \"ts\":\"09.10.22 08:34:12\",\t \"ort\":\"Keller\"\t },\t {\t \"window\":\"Billard_Fenster\",\t \"status\":\"closed\",\t \"ts\":\"09.10.22 08:33:57\",\t \"ort\":\"Keller\"\t },\t {\t \"window\":\"Vorratsraum_Fenster\",\t \"status\":\"closed\",\t \"ts\":\"09.10.22 08:33:38\",\t \"ort\":\"Keller\"\t },\t {\t \"window\":\"Keller\",\t \"status\":\"closed\",\t \"ts\":\"09.10.22 08:33:36\",\t \"ort\":\"Keller\"\t },\t {\t \"window\":\"EWerkstatt_Fenster\",\t \"status\":\"closed\",\t \"ts\":\"09.10.22 05:00:27\",\t \"ort\":\"Keller\"\t },\t {\t \"window\":\"Safe\",\t \"status\":\"closed\",\t \"ts\":\"09.10.22 04:36:26\",\t \"ort\":\"Keller\"\t },\t {\t \"window\":\"Schlafstube_Fenster_links\",\t \"status\":\"closed\",\t \"ts\":\"09.10.22 08:35:42\",\t \"ort\":\"OG\"\t },\t {\t \"window\":\"Schlafstube_Fenster_rechts\",\t \"status\":\"closed\",\t \"ts\":\"09.10.22 08:31:45\",\t \"ort\":\"OG\"\t },\t {\t \"window\":\"OG_Kinderzimmer_Fenster\",\t \"status\":\"closed\",\t \"ts\":\"09.10.22 02:51:01\",\t \"ort\":\"OG\"\t }\t]",
"payloadType": "jsonata",
"x": 400,
"y": 400,
"wires": [
[
"a361f3170fba9d32"
]
]
},
{
"id": "87e32ce83242e0f3",
"type": "ui_group",
"name": "offene Fenster",
"tab": "a96d3174521b3e8e",
"order": 2,
"disp": true,
"width": 9,
"collapse": true,
"className": ""
},
{
"id": "a96d3174521b3e8e",
"type": "ui_tab",
"name": "Listen ",
"icon": "list",
"disabled": false,
"hidden": false
}
]
In the production system the table is much bigger. This still works without problems, but I get a hint in the browser console:
[Warning] Table Not Initialized - Calling the replaceData function before the table is initialized may result in inconsistent behavior, Please wait for the tableBuilt
event before calling this function. (ui, line 2)
Here is the code from the ui-template:
<link href="https://unpkg.com/tabulator-tables@5.4/dist/css/tabulator.min.css" rel="stylesheet">
<script type="text/javascript" src="https://unpkg.com/tabulator-tables@5.4/dist/js/tabulator.min.js"></script>
<div id="openWindowsTable"></div>
<script>
var table = new Tabulator("#openWindowsTable", {
height:"700px" ,
placeholder:"Keine Daten verfügbar!",
layout: "fitDataStretch",
movableColumns: true,
/*allow column order to be changed*/
/*colums format definitions*/
columns: [{
title: "Fenster",
field: "window",
width: 250
},
{
title: "Status",
field: "status",
formatter: function(cell, formatterParams, onRendered){
//cell - the cell component
//formatterParams - parameters set for the column
//onRendered - function to call when the formatter has been rendered
return "<span style='color:Black; font-weight:bold;'>" + cell.getValue() + "</span>"
},
},
{
title: "Zeit",
field: "ts",
},
],
columnDefaults:{
tooltip:true,
},
/*initial sorting */
initialSort:[
{column:"status", dir:"desc"}, //sort by this first
{column:"ts", dir:"desc"}, //then sort by this second
],
/* group by ort*/
groupBy: "ort",
groupStartOpen: true,
/* format groupHeader */
groupHeader: function(value, count, data, group) {
var r = "<span style='color:#d00; margin-left:10px;'>(" + count + " Fenster)</span>";
return value + r;
},
/*format individal cell*/
rowFormatter: function(row) {
const cl = row.getCells();
cl[1].getElement().style.backgroundColor = (cl[1]._cell.value === 'open' ? '#F1948A' : '#82E0AA');
},
});
/* events */
table.on("renderComplete",function() {
let data = table.getData();
let groupHeaderList = document.querySelectorAll(".tabulator-row.tabulator-group");
let groups = Array.from(groupHeaderList, (group) => group.outerText.split('(')[0]);
for (let i = 0; i < groups.length; i++) { const group=groups[i]; const statusOpen=data.some(g=> g.ort === group &&
g.status === 'open');
groupHeaderList[i].style.backgroundColor = (statusOpen) ? '#E74C3C' : '#2ECC71';
}
});
table.on("tableBuilt", function() {return console.log("from tableBuilt event")});
(function(scope) {
scope.$watch('msg', function(msg) {
if(msg) {
var tabledata = msg.payload;
table.replaceData(tabledata);
}
});
})(scope);
</script>
I don't know how to make table.replaceData(tabledata); in scope.$watch wait for the tableBuild event though?
Can someone help me with this?