Ui-table with dropdown list

Hi there!
I am using ui-table and the ui-table handler from @Christian-Me and like it a lot.
Currently I am trying to work out how to populate the values of dropdown lists in the cell-editor of the underlying tabulator (section: "select"): http://tabulator.info/docs/4.4/edit#edit-builtin
So far I managed to get a value list correctly configured. Also I got the value list populated by means of a function for the "editorParameters".
image
Also I got the value list populated by means of a function for the "editorParams".

function(cell){
	var myValues = ["apples","pears","blueberries","oranges"];
	return {values:myValues,showListOnEmpty: true};
}

Now I would like to take the next step and retrieve the values list from the flow context.
Is that possible?
How would I need to put this into the function? Is that the right spot to insert it?
So far I tried this which didnt work:

function(cell){
	var myValues = flow.get("listValues")||[];
	return {values:myValues,showListOnEmpty: true};
}

OR
Is passing the "tabulator" parameter to the ui-table handler node an option to update the values?
Thanks a lot!
JR

Edit: I tried to use the command functionality directly to the ui-table node, but it seems the ui-table node does not support the commands getColumnLayout and setColumnLayout.

My advice, skip ui-table and use ui-template instead to make your Tabulator tables. The functionality of Tabulator itself is so much easier to use in its raw form than through the outdated wrapper of ui-table. You already have a lot of understanding of how Tabulator works. Just use ui-templates instead and put the code in there based on the Tabulator documentation you're already reading.

It's a bit of work to get it setup and there's a learning curve to how to implement interactions, but once you have the basics, it becomes really easy compared to ui-table.

Hi madhouse!
Thanks for your feedback! It is good to know that using tabulator directly in a template node works.
At the current stage of the project I am less inclined to change. In the next sub-project I am considering this option. Is it possible to use any version of tabulator in such a setup (the later version have great imrovements in terms of data manipulation and checking)? Are you willing to share an example flow of how to integrate tabulator into a template node?

As for the problem at hand I found out that the ui-table handler accepts a msg.ui_control in which a full new table setup can be passed, which is used for the current message processing. One needs to remember to reuse that updated table setup in all following messages.
So I basically keep updating the ui_control with the new dropdown selection items. For me this works as this needs to be updated seldom.

[{"id":"c875aa3.cc01b58","type":"function","z":"df22847e.c06768","name":"update selection lists","func":"// check also the OnStart tab! It sets the basic configuration\nvar newMsg = {};\n\n// command for ui-table handler\nnewMsg.command = \"refreshTable\";\nnewMsg.argument = \"\";\n\nlet ui_control = flow.get(\"tableUIcontrol\");\nif(ui_control){\n    // Finding index of the car with column \"program\" \n    const searchIndex = ui_control.tabulator.columns.findIndex((column) => column.field==\"program\");\n    \n    // Update the value list for the respective column\n    // ui_control.tabulator.columns[searchIndex].editorParams.values = flow.get(\"listValues\"); //alternative\n    ui_control.tabulator.columns[searchIndex].editorParams.values = [\"my\",\"new\",\"list\",\"values\"];\n    \n    // save for later reuse\n    flow.set(\"tableUIcontrol\",ui_control);\n    newMsg.ui_control = ui_control;\n}\n\nreturn newMsg;","outputs":1,"noerr":0,"initialize":"// Code added here will be run once\n// whenever the node is started.\nflow.set(\"tableUIcontrol\",{\n    \"customHeight\": 18,\n    \"tabulator\": {\n        \"index\": \"id\",\n        \"layout\": \"fitColumns\",\n        \"movableColumns\": true,\n        \"autoColumns\": true,\n        \"columns\": [\n            {\n                \"title\": \"pos\",\n                \"field\": \"id\",\n                \"headerSort\": false,\n                \"width\": 55\n            },\n            {\n                \"title\": \"min\",\n                \"field\": \"min\",\n                \"headerSort\": false,\n                \"editor\": \"number\",\n                \"editorParams\": {\n                    \"min\": 0,\n                    \"max\": 359,\n                    \"step\": 1\n                },\n                \"width\": 70\n            },\n            {\n                \"title\": \"max\",\n                \"field\": \"max\",\n                \"headerSort\": false,\n                \"editor\": \"number\",\n                \"editorParams\": {\n                    \"min\": 0,\n                    \"max\": 359,\n                    \"step\": 1\n                },\n                \"width\": 70\n            },\n            {\n                \"title\": \"Programm\",\n                \"field\": \"program\",\n                \"headerSort\": false,\n                \"editor\": \"autocomplete\",\n                \"editorParams\": {\n                    \"freetext\": false,\n                    \"allowEmpty\": false,\n                    \"showListOnEmpty\": true,\n                    \"values\": [\n                        \"red\",\n                        \"green\",\n                        \"blue\",\n                        \"orange\"\n                    ]\n                }\n            },\n            {\n                \"title\": \"Kontext 1\",\n                \"field\": \"context1\",\n                \"headerSort\": false,\n                \"editor\": \"autocomplete\",\n                \"editorParams\": {\n                    \"showListOnEmpty\": true,\n                    \"values\":[\"\"]\n                }\n            },\n            {\n                \"field\": \"up\",\n                \"formatter\": \"function(cell, formatterParams, onRendered){     var html=\\\"<i class=\\\\\\\"fa fa-arrow-up\\\\\\\"></i>\\\";     return html; }\",\n                \"headerSort\": false,\n                \"width\": 10,\n                \"align\": \"center\"\n            },\n            {\n                \"field\": \"down\",\n                \"formatter\": \"function(cell, formatterParams, onRendered){     var html=\\\"<i class=\\\\\\\"fa fa-arrow-down\\\\\\\"></i>\\\";     return html; }\",\n                \"headerSort\": false,\n                \"width\": 10,\n                \"align\": \"center\"\n            }\n        ],\n        \"cellEdited\": \"function (cell) {     this.send(         {              ui_control: {callback:'cellEdited'},                               payload: cell.getValue(),                      oldValue: cell.getOldValue(),                      field: cell.getColumn().getField(),                      id: cell.getRow().getCell('id').getValue()     }); }\",\n        \"columnResized\": \"function(column){     var newColumn = {         field: column._column.field,         visible: column._column.visible,         width: column._column.width,         widthFixed: column._column.widthFixed,         widthStyled: column._column.widthStyled     }; this.send({topic:this.config.topic,ui_control:{callback:'columnResized',columnWidths:newColumn}}); }\",\n        \"columnMoved\": \"function(column, columns){     var newColumns=[];     columns.forEach(function (column) {         newColumns.push({'field': column._column.definition.field, 'title': column._column.definition.title});     });     this.send({topic:this.config.topic,ui_control:{callback:'columnMoved',columns:newColumns}}); }\",\n        \"rowMoved\": \"function(row){     var rowOrder=[];     row._row.parent.rows.forEach((row,index) => {         rowOrder.push(row.data.id);     });     this.send({ui_control:{\\\"callback\\\":'rowMoved',\\\"rowOrder\\\":rowOrder}}); }\"\n    }\n})","finalize":"","libs":[],"x":280,"y":1600,"wires":[["ebc51e96.75e7f","a32d36c8.69d0c8"]]},{"id":"40b94c5b.75ed44","type":"inject","z":"df22847e.c06768","name":"trig","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":90,"y":1600,"wires":[["c875aa3.cc01b58"]]},{"id":"ebc51e96.75e7f","type":"function","z":"df22847e.c06768","name":"ui-table handler (placeholder)","func":"\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":530,"y":1600,"wires":[["888a468a.3245e8"]]},{"id":"888a468a.3245e8","type":"debug","z":"df22847e.c06768","name":"list update","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":770,"y":1600,"wires":[]}]

Cheers
JR

That's a fair statement. But I believe that when you see how easy Tabulator is to work with once you have it started, you'll swap everything over. There is one caveat though. Ui-table forces the old version of Tabulator on your page, so you can't utilize the new version either without some fancy HTTP trickery or by taking everything to straight Tabulator. Which is really easy.

You need at least these two nodes to start with.
image

[{"id":"3e5b8cea59cf2699","type":"ui_template","z":"1408108b8b13c0b7","group":"d386fb82fa5ef195","name":"Header","order":6,"width":0,"height":0,"format":"<link href=\"https://unpkg.com/tabulator-tables/dist/css/tabulator_midnight.min.css\" rel=\"stylesheet\">\n<script type=\"text/javascript\" src=\"https://unpkg.com/tabulator-tables/dist/js/tabulator.min.js\"></script>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"global","className":"","x":100,"y":40,"wires":[[]]},{"id":"2c5713572a463bf1","type":"ui_template","z":"1408108b8b13c0b7","group":"d386fb82fa5ef195","name":"Tabulator","order":7,"width":0,"height":0,"format":"<div id=\"example-table\"></div>\n<script>\n    //Copy/paste Tabulator examples directly from the web page here.\n    //You will need example data to use them directly.\n    //Otherwise copy the examples and alter to your needs.\n    //Most of the following is directly from the quickstart page.\n    \n    var tabledata = [\n    \t{id:1, name:\"Oli Bob\", age:\"12\", col:\"red\", dob:\"\"},\n    \t{id:2, name:\"Mary May\", age:\"1\", col:\"blue\", dob:\"14/05/1982\"},\n    \t{id:3, name:\"Christine Lobowski\", age:\"42\", col:\"green\", dob:\"22/05/1982\"},\n    \t{id:4, name:\"Brendon Philips\", age:\"125\", col:\"orange\", dob:\"01/08/1980\"},\n    \t{id:5, name:\"Margret Marmajuke\", age:\"16\", col:\"yellow\", dob:\"31/01/1999\"},\n    ];\n    \n    var table = new Tabulator(\"#example-table\", {\n     \theight:205, // set height of table (in CSS or here), this enables the Virtual DOM and improves render speed dramatically (can be any valid css height value)\n     \tdata:tabledata, //assign data to table\n     \tlayout:\"fitColumns\", //fit columns to width of table (optional)\n     \tcolumns:[ //Define Table Columns\n    \t \t{title:\"Name\", field:\"name\", width:150},\n    \t \t{title:\"Age\", field:\"age\", hozAlign:\"left\", formatter:\"progress\"},\n    \t \t{title:\"Favourite Color\", field:\"col\"},\n    \t \t{title:\"Date Of Birth\", field:\"dob\", sorter:\"date\", hozAlign:\"center\"},\n     \t],\n    });\n    \n    table.on(\"rowClick\", function(e, row){ \n    \talert(\"Row \" + row.getData().id + \" Clicked!!!!\");\n    });\n    \n    //This is needed to interact with Node-Red when a message is sent to the ui-template.\n    (function(scope){\n        scope.$watch('msg', function(msg){\n            if(msg){\n                //do something here when a message arrives like table.setData();\n            }\n        });\n    })(scope);\n</script>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":100,"y":80,"wires":[[]]},{"id":"d386fb82fa5ef195","type":"ui_group","name":"Tabulator Example","tab":"d0ef1a9bfa867de7","order":3,"disp":true,"width":"16","collapse":true,"className":""},{"id":"d0ef1a9bfa867de7","type":"ui_tab","name":"Tabulator","icon":"dashboard","order":1,"disabled":false,"hidden":false}]

What this will do is create a table that simply displays data with some miniscule amount of interaction. Simply change what needs to be changed based on the information on Tabulator's website and you're good to go. There's a snippet at the end of the Tabulator node that you'll need to react to messages sent to the template node. Since the Template node is running on the client system and not the server, there's no way of directly interacting with it like the other Node-Red nodes. But putting that snippet into the node will allow it to catch the messages and react. This is a good place to put things like functions for refreshing data and such.

Uggghhh... Once I figured out AJAX handling, I quit passing whole tables. Simply putting everything in a file and letting it do its own thing was magical. The easiest solution I found so far (I realize there are others that could be better) was to use HTTP in and out nodes. Call an HTTP in node in GET mode from Tabulator (i.e. the ajaxURL option), hook that in node to a file reader, hook that to a JSON parser and finish off the string with an HTTP out node to return the result. Now everytime you call table.setData(), it will pull the updated contents of the file. To update the file, use fetch() to POST the data to an HTTP in node configured in POST (will need to be a different address than your GET node), run it to a file write node and send the output to an HTTP out node. Instant read/write capabilities. And if you want to refresh your table whenever data is saved, just run the output of the file write node to the input of the ui-template node with the table and react to the message. Easy.

Obviously you won't care about things you won't use much. You don't need to update a Tabulator table with new dropdowns since you can write functions within the column description that will change the contents of the dropdown for you based on some other data in the table or variable in the program.

Anyways, that's a quickstart to using Tabulator in Node-Red. Let me know if you have any issues besides it not working correctly due to a ui-table node still being used. I'm going to expect that one as long as one exists. I got rid of all of mine and went straight Tabulator only. But that's me. You'll do what works the best for you. I wish you well with your newfound knowledge.

Thanks a lot madhouse!!
It sounds quite doable. And yes, the functions tabulator offers to update and manipulate data are quite tempting and I found it a pity that they are not exposed on the ui-table node. Though I can understand some of the complications this could potentially bring. So an integration by template seems more feasable.
Once I am at the point of changing for sure I will come back to your advice! :wink: :wink:
Cheers
JR

Welcome! Glad I could help.

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