# Ui-table in conjunction with ui-table handler

**URL:** <https://discourse.nodered.org/t/ui-table-in-conjunction-with-ui-table-handler/56554>\
**Category:** General\
**Created:** [12 January 2022 22:49 UTC](https://discourse.nodered.org/t/ui-table-in-conjunction-with-ui-table-handler/56554 "2022-01-12T22:49:30Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![ceysa75](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ceysa75/32/31340_2.png) [@ceysa75](https://discourse.nodered.org/u/ceysa75)\
**Post date:** [12 January 2022 22:49 UTC](https://discourse.nodered.org/t/ui-table-in-conjunction-with-ui-table-handler/56554/1 "2022-01-12T22:49:30Z")

</div>

Hi all,

I must say that the table situation in Node-Red is quite challenging, at least from a beginners perspective. And dont get me wrong, of course versatile tools as ui-tabe a very powerful. I am just thinking about very simple tables where individual cells could be updated without higher programming effort.

Therefore I really appreciate the efforts of @Christian-Me for providing a handy tool (ui-table handler) serving as interface between the input data and ui-table.  
But Chris, what would really help is a minimum working example. BTW: It's worth thinking about to provide one in the flow section together with your subflow. As a matter of fact I am not able to make it work. Below I have provided a small example flow. Could you please help sorting my issues out ? I think, the example is self-explanatory. Your help is really appreciated.

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/9/b/9bec61c84538e30b2f595720a5fc878f11d4e5e9.png)

[PASTEBIN-Link](https://pastebin.com/V0Ku7pF4)

Sorry for using an external link, but I could not insert the flow here (Body is limited to 32000 characters; you entered sth \> 32000). I think this comes from your subflow 😉

---

<div class="post-metadata">

**Author:** ![Christian-Me](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/christian-me/32/10774_2.png) [@Christian-Me](https://discourse.nodered.org/u/Christian-Me)\
**Post date:** [12 January 2022 22:54 UTC](https://discourse.nodered.org/t/ui-table-in-conjunction-with-ui-table-handler/56554/2 "2022-01-12T22:54:37Z")

</div>

Have you tried this demo I prepared recently:

> [@Get ui-table data in JSON format](https://discourse.nodered.org/t/get-ui-table-data-in-json-format/55262/11):
>
> Hi @ataelim, @Henjoe I prepared a demo flow: I recognized that the table handler not working well with the table data send as msg.payload so I did a few updates. That should work now. (OMG my own legacy code rofl). So please make sure that you get version 0.2.1 [image] I recognized that sorting/moving columns is not working (as expected) any more. They either don't restore or are in a strange place. Have to go into the code of ui-table itself as the columns configs are merged the…

---

<div class="post-metadata">

**Author:** ![ceysa75](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ceysa75/32/31340_2.png) [@ceysa75](https://discourse.nodered.org/u/ceysa75)\
**Post date:** [13 January 2022 08:02 UTC](https://discourse.nodered.org/t/ui-table-in-conjunction-with-ui-table-handler/56554/3 "2022-01-13T08:02:18Z")

</div>

Thanks CHris for the fast response,

No, haven't found this demo. Just downloaded it and will investigate. Thanks. I just have realized, that you have made a new version. Thanks. Will report later.

Thanks again (also writing from Berlin ;-))

---

<div class="post-metadata">

**Author:** ![ceysa75](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ceysa75/32/31340_2.png) [@ceysa75](https://discourse.nodered.org/u/ceysa75)\
**Post date:** [13 January 2022 21:30 UTC](https://discourse.nodered.org/t/ui-table-in-conjunction-with-ui-table-handler/56554/4 "2022-01-13T21:30:30Z")

</div>

Dear @Christian-Me,

this is all fabulous. I understood the working principle so far. Really good job. I even have started playing around with styling and layout. That is easier than expected... Thank you so much 😃

I wonder if you may help me finding a solution for the following situation: I would like to change the text color of individual cells depending on the value. E.g. for values between 100-70:green, 70-40:orange and 40-0:red. I have already realized that using the progress bar (as built in function in Tabulator). However, the changing text color corresponds to what I am actually looking for. Do you know any examples where this was done ?

However, whatever your answer will be... Thank you so much!

---

<div class="post-metadata">

**Author:** ![Christian-Me](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/christian-me/32/10774_2.png) [@Christian-Me](https://discourse.nodered.org/u/Christian-Me)\
**Post date:** [14 January 2022 00:29 UTC](https://discourse.nodered.org/t/ui-table-in-conjunction-with-ui-table-handler/56554/5 "2022-01-14T00:29:37Z")

</div>

Hi .... Yes This can be done.

It was in my 1st table you can find in the examples. This is the HTML Version (look into column `BOOST_STATE-value`

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/2/5/25a2f405d55c21caa3376608e079fa84e0db2132.png)

but the more elegant way to do:

- you will need a formatter callback [more here](http://tabulator.info/docs/4.3/format#format-custom)
- I use a function node as an editor and the copy paste it into the visual JSON editor (to escape all inverted commas) CTRL-A + CTRL-V

```auto
var customFormatter = function (cell, formatterParams, onRendered) {
    //cell - the cell component
    //formatterParams - parameters set for the column
    //onRendered - function to call when the formatter has been rendered

    let value = cell.getValue();
    let color = 'orange';
    if (value < 40) {
        color = 'red';
    } else if (value > 70) {
        color = 'green';
    }
    cell.getElement().style.color = color;

    return value;
}

```

copy everything from `function ( ... }` into the `formatter` value.

Tip: The callbacks are running in the dashboard / browser so use the development tools for debugging. simple `console.log()` might help for easy bugs

You can alter the DOM with the `style` object ... so a lot of possibilities!

Good night 😉

---

<div class="post-metadata">

**Author:** ![ceysa75](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ceysa75/32/31340_2.png) [@ceysa75](https://discourse.nodered.org/u/ceysa75)\
**Post date:** [14 January 2022 23:15 UTC](https://discourse.nodered.org/t/ui-table-in-conjunction-with-ui-table-handler/56554/6 "2022-01-14T23:15:49Z")

</div>

For the record and all forum members,

this is how I solved the conditional text colors...

```auto
 {
                "title": "<i class='fa fa-clock-o'></i>&nbsp;Last seen",
                "field": "lastseen",
                "formatter": "function(cell, formatterParams, onRendered){var value = cell.getValue(); if(value < 60) {cell.getElement().style.color=\"green\";} else {cell.getElement().style.color=\"red\";} return value+'&nbsp;&nbsp;'+'minutes';}"
            }

```

---

<div class="post-metadata">

**Author:** ![ceysa75](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ceysa75/32/31340_2.png) [@ceysa75](https://discourse.nodered.org/u/ceysa75)\
**Post date:** [19 January 2022 23:25 UTC](https://discourse.nodered.org/t/ui-table-in-conjunction-with-ui-table-handler/56554/7 "2022-01-19T23:25:08Z")

</div>

Hi @Christian-Me,

I am getting deeper and deeper into this table stuff (quite time consuming I must admit, but I thinks it's worth spending time here). Maybe a bit naive but I am trying to 'change' the cell values. E.g. the table gets minutes. If the value is less than 60 minutes I would like to have minutes. For larger values I would like to have hours. Additionally, for times larger than 12 hours the text colour should change to red. I tried to perform these calucaltions directly in the formatter. However, apparently I am on a completely wrong way. Do you have any suggestions how to achieve that ?

```auto
function(cell, formatterParams, onRendered) {
var value = cell.getValue(); 
if(value < 60) {
cell.getElement().style.color="lime";
result = value + '&nbsp;&nbsp;' + 'Min';
} else if (value >60 && value <= 720) {
cell.getElement().style.color="lime";
hrs = Math.floor(value/60);
result = hrs + '&nbsp;&nbsp;' + 'Std';
}
else {
cell.getElement().style.color="coral";
hrs = Math.floor(value/60);
result = hrs + '&nbsp;&nbsp;' + 'Std';
}
return result;
}

```

Regards...

---

<div class="post-metadata">

**Author:** ![Christian-Me](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/christian-me/32/10774_2.png) [@Christian-Me](https://discourse.nodered.org/u/Christian-Me)\
**Post date:** [20 January 2022 08:16 UTC](https://discourse.nodered.org/t/ui-table-in-conjunction-with-ui-table-handler/56554/8 "2022-01-20T08:16:32Z")

</div>

Looking at the code everything looks totally fine. It will format the content and style the color of the text.

I believe you like to implement something like "last seen" or "last update". I think you can't do it with ui-table run on its own. But if you send regular updates in the interval you need it isn't difficult:

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/1/7/1749f78e77b602a6e3964ebc3382e46d468344ca.png)

The trigger simulates a new update (reset last seen with a new timestamp). update Data does simple "formatting". The trigger node resents the last seen timestamp and delta does a simple `Date.now()-timestamp`

The formatter then looks like this (I reduced it to seconds for faster debugging)

```auto
function (cell, formatterParams, onRendered) {
    let updatedSince = Number(cell.getValue());
    if (Number.isNaN(updatedSince)) {
        cell.getElement().style.color = 'red';
        return 'never';
    }
    if (updatedSince < 10) {
        cell.getElement().style.color = 'lime';
        return updatedSince + '&nbsp;&nbsp;' + 's (<10)';
    } else if (updatedSince < 20) {
        cell.getElement().style.color = 'orange';
        return updatedSince + '&nbsp;&nbsp;' + 's (<20)';
    }
    cell.getElement().style.color = 'coral';
    return updatedSince + '&nbsp;&nbsp;' + 's (>20)';
}

```

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/8/e/8e8d6912f7df9a58d57114a3d38d4d83528849c9.png)

Simply feed this flow into the ui-table-handler and add the "lastSeen" column

```auto
[{"id":"b6d568762ff16077","type":"trigger","z":"d2952ff54c89c139","name":"","op1":"","op2":"0","op1type":"pay","op2type":"str","duration":"-1","extend":false,"overrideDelay":false,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":500,"y":1540,"wires":[["333515516f7ae884"]]},{"id":"df10a25a5973aef6","type":"inject","z":"d2952ff54c89c139","name":"trigger","props":[{"p":"payload"},{"p":"index","v":"1","vt":"num"},{"p":"column","v":"lastSeen","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payloadType":"date","x":170,"y":1540,"wires":[["d449b1a7538a3949"]]},{"id":"d449b1a7538a3949","type":"function","z":"d2952ff54c89c139","name":"update Data","func":"let value = msg.payload;\nmsg.payload = { id: msg.index};\nmsg.payload[msg.column] = value;\nreturn msg;","outputs":1,"noerr":0,"initialize":"// Code added here will be run once\n// whenever the node is started.\ncontext.set('index',0);","finalize":"","libs":[],"x":310,"y":1540,"wires":[["b6d568762ff16077"]]},{"id":"b56f7f19a054d87b","type":"debug","z":"d2952ff54c89c139","name":"update","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":810,"y":1540,"wires":[]},{"id":"89ac1fed6b1e1132","type":"inject","z":"d2952ff54c89c139","name":"reset","props":[{"p":"reset","v":"true","vt":"bool"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":330,"y":1580,"wires":[["b6d568762ff16077"]]},{"id":"333515516f7ae884","type":"function","z":"d2952ff54c89c139","name":"delta","func":"msg.payload.lastSeen = Math.floor((Date.now() - msg.payload.lastSeen) / 1000);\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":650,"y":1540,"wires":[["b952ac65.8ddfb","b56f7f19a054d87b"]]}]

```

I first tried only to resend the "lastSeen" timestamp. This does not work because the cell formatter is only triggered if the value changes. For many rows you should think about sending an array of all rows every minute (as this is your desired scope) to the table handler.

A last tip: Use a "unconnected" function node to edit your callbacks and then copy past the function into your JSON via the Visual Editor. By doing so you can take advantage of the syntax checking (i.e. undeclared variables) and don't worry about escaping inverted commas ... Don't use comments as they might break the complete code behind the comment as CR seams not to be translated into `/n`

---

<div class="post-metadata">

**Author:** ![ceysa75](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ceysa75/32/31340_2.png) [@ceysa75](https://discourse.nodered.org/u/ceysa75)\
**Post date:** [20 January 2022 14:56 UTC](https://discourse.nodered.org/t/ui-table-in-conjunction-with-ui-table-handler/56554/9 "2022-01-20T14:56:46Z")

</div>

Chris,

Thanks once more for your entiring effort. This is all great and useful. However, my basic point here was the possibility to perform smaller calculations directly in the formatter. As shown above e.g. to calculate hours from minutes etc. At least during my tests that didn't work.

---

<div class="post-metadata">

**Author:** ![Christian-Me](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/christian-me/32/10774_2.png) [@Christian-Me](https://discourse.nodered.org/u/Christian-Me)\
**Post date:** [20 January 2022 23:38 UTC](https://discourse.nodered.org/t/ui-table-in-conjunction-with-ui-table-handler/56554/10 "2022-01-20T23:38:03Z")

</div>

Than my last paragraph is relevant:

> [@Christian-Me](#):
>
> By doing so you can take advantage of the syntax checking (i.e. undeclared variables) and don't worry about escaping inverted commas

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/6/3/63751b91747f0c6a5e44fca390b378aec272fc0a.png)

so addressing the issues here like this  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/f/f/ffc1bded70074d34b066d563f36c072107c4b8ca.png)

gives you this

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/8/7/8790aa90407ba65da2b2a40134d77ee728b143d3.png)

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/7/a/7a7401c639b6920488687580eaa2c4ec7ce48b71.png)

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/5/7/57131456cdc05f3476a9e9e0706b5b4ce451ca23.png)

So everything as you could expect it.

But even with your issues the callback works as expected (at least when tested it)

So perhaps take a look in your browsers console or place a simple `console.log({cell, formatterParams, onRendered, value:cell.getValue()});` at the beginning of your callback to check if it's even triggered. (sometimes refreshing the browser could help)

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/b/8/b8083aec3e57e18f3004c7cf4323a4bc3e6c438f.png)

my demo data (expecting the callback in column `test`)

```auto
[{"id":"b974034a6e684cc8","type":"inject","z":"d2952ff54c89c139","name":"10","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"id\":2,\"test\":10}","payloadType":"json","x":190,"y":1660,"wires":[["3eda5cde9960731e"]]},{"id":"838e6b908e503b50","type":"inject","z":"d2952ff54c89c139","name":"80","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"id\":2,\"test\":80}","payloadType":"json","x":190,"y":1700,"wires":[["3eda5cde9960731e"]]},{"id":"8d63651866a8414d","type":"inject","z":"d2952ff54c89c139","name":"800","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"id\":2,\"test\":800}","payloadType":"json","x":190,"y":1740,"wires":[["3eda5cde9960731e"]]},{"id":"3eda5cde9960731e","type":"link out","z":"d2952ff54c89c139","name":"table","mode":"link","links":["d010ebc3f8435624"],"x":305,"y":1700,"wires":[]}]

```

> [@ceysa75](#):
>
> However, my basic point here was the possibility to perform smaller calculations directly in the formatter

Yes! Not only basic stuff ... you have access to the DOM and and the complete table content via the cell component

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [21 March 2022 23:38 UTC](https://discourse.nodered.org/t/ui-table-in-conjunction-with-ui-table-handler/56554/11 "2022-03-21T23:38:30Z")

</div>

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