Using ui_table 'tickCross' colorization?

Comparing ui_table tickCloss formatter to the tabulator examples, I noticed that the tickCross is the same color be it true/false or 1/0. Is there a way to color the tick or cross? For example, for tick use the default theme color, but if a cross, say red?

I am already using a render function to colorize the entire row, so if I change the foreground color would that do it? Just not sure how the tick/cross code logic works.

I tried this... but did not seem to work...

 "formatter": "function(cell, formatterParams, onRendered) { var status = cell.getValue(); if (status===false) { cell.getElement().style.color='red'; } return status; }",

I tweaked the ui_table example that uses a msg.ui_control configuration.
When the formatter is tickCross you can use the tickElement and crossElement with added custom styling.

In the tickElement, you can see that i used the
color:var(--nr-dashboard-pageTitlebarBackgroundColor)
so the tick matches the Dashboard default theme color.

{
                        "formatterParams": {
                            "target": "_blank",
                            "allowEmpty": true,
                            "allowTruthy": true,
                            "tickElement": "<i class='fa fa-check' style='color:var(--nr-dashboard-pageTitlebarBackgroundColor)'></i>",
                            "crossElement": "<i class='fa fa-times-circle' style='color:red;'></i>"
                        },
                        "title": "Auto",
                        "field": "AUTO_MODE-value",
                        "formatter": "tickCross",
                        "width": 100,
                        "align": "center"
                    },

Demo Flow:

image

[{"id":"adea6a2e180d669f","type":"inject","z":"54efb553244c241f","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[{\"name\":\"MEQ0451495\",\"room\":\"Bathroom\",\"SET_TEMPERATURE-value\":22,\"ACTUAL_TEMPERATURE-value\":21.8,\"VALVE_STATE-value\":90,\"BATTERY_STATE-value\":2.7,\"BOOST_STATE-value\":0,\"AUTO_MODE-value\":true,\"CONTROL_MODE-value\":0},{\"name\":\"MEQ1875547\",\"room\":\"Living Room\",\"SET_TEMPERATURE-value\":12,\"ACTUAL_TEMPERATURE-value\":16.2,\"VALVE_STATE-value\":0,\"BATTERY_STATE-value\":2.7,\"BOOST_STATE-value\":0,\"AUTO_MODE-value\":true,\"CONTROL_MODE-value\":1},{\"name\":\"MEQ1875538\",\"room\":\"Living Room\",\"SET_TEMPERATURE-value\":18,\"ACTUAL_TEMPERATURE-value\":19.5,\"VALVE_STATE-value\":0,\"BATTERY_STATE-value\":2.6,\"BOOST_STATE-value\":0,\"AUTO_MODE-value\":false,\"CONTROL_MODE-value\":2},{\"name\":\"MEQ0447462\",\"room\":\"Kitchen\",\"SET_TEMPERATURE-value\":17,\"ACTUAL_TEMPERATURE-value\":22.2,\"VALVE_STATE-value\":0,\"BATTERY_STATE-value\":2.7,\"BOOST_STATE-value\":10,\"AUTO_MODE-value\":true,\"CONTROL_MODE-value\":3},{\"name\":\"MEQ1875551\",\"room\":\"Office\",\"SET_TEMPERATURE-value\":18,\"ACTUAL_TEMPERATURE-value\":20.2,\"VALVE_STATE-value\":0,\"BATTERY_STATE-value\":2.7,\"BOOST_STATE-value\":0,\"AUTO_MODE-value\":false,\"CONTROL_MODE-value\":0},{\"name\":\"MEQ0447425\",\"room\":\"Dining Room\",\"SET_TEMPERATURE-value\":19,\"ACTUAL_TEMPERATURE-value\":20.4,\"VALVE_STATE-value\":0,\"BATTERY_STATE-value\":2.7,\"BOOST_STATE-value\":0,\"AUTO_MODE-value\":false,\"CONTROL_MODE-value\":0},{\"name\":\"MEQ1875546\",\"room\":\"Dining Room\",\"SET_TEMPERATURE-value\":20,\"ACTUAL_TEMPERATURE-value\":18.8,\"VALVE_STATE-value\":99,\"BATTERY_STATE-value\":2.7,\"BOOST_STATE-value\":0,\"AUTO_MODE-value\":false,\"CONTROL_MODE-value\":0},{\"name\":\"MEQ0447483\",\"room\":\"Bedroom\",\"SET_TEMPERATURE-value\":17,\"ACTUAL_TEMPERATURE-value\":22.4,\"VALVE_STATE-value\":0,\"BATTERY_STATE-value\":2.7,\"BOOST_STATE-value\":0,\"AUTO_MODE-value\":true,\"CONTROL_MODE-value\":0},{\"name\":\"MEQ1875541\",\"room\":\"Child\",\"SET_TEMPERATURE-value\":18,\"ACTUAL_TEMPERATURE-value\":20.4,\"VALVE_STATE-value\":0,\"BATTERY_STATE-value\":2.7,\"BOOST_STATE-value\":0,\"AUTO_MODE-value\":false,\"CONTROL_MODE-value\":0},{\"name\":\"MEQ1875552\",\"room\":\"Guest Room\",\"SET_TEMPERATURE-value\":20,\"ACTUAL_TEMPERATURE-value\":21.1,\"VALVE_STATE-value\":9,\"BATTERY_STATE-value\":2.8,\"BOOST_STATE-value\":0,\"AUTO_MODE-value\":false,\"CONTROL_MODE-value\":0}]","payloadType":"json","x":290,"y":2460,"wires":[["a2b00c70628bd27e"]]},{"id":"a2b00c70628bd27e","type":"change","z":"54efb553244c241f","name":"ui_control","rules":[{"t":"set","p":"ui_control","pt":"msg","to":"{\"tabulator\":{\"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}}); }\",\"columnMoved\":\"function(column, columns){     var newColumns=[];     columns.forEach(function (column) {         newColumns.push({'field': column._column.field});     });     this.send({topic:this.config.topic,ui_control:{callback:'columnMoved',columns:newColumns}}); }\",\"groupHeader\":\"function (value, count, data, group) {return value + \\\"<span style='color:#d00; margin-left:10px;'>(\\\" + count + \\\" Termostat\\\"+((count>1) ? \\\"e\\\" : \\\"\\\") + \\\")</span>\\\";}\",\"columns\":[{\"formatterParams\":{\"target\":\"_blank\"},\"title\":\"ROom\",\"field\":\"room\",\"width\":100,\"frozen\":true},{\"formatterParams\":{\"target\":\"_blank\"},\"title\":\"Device\",\"field\":\"name\",\"width\":100,\"align\":\"center\"},{\"formatterParams\":{\"target\":\"_blank\"},\"title\":\"Type\",\"field\":\"deviceType\",\"width\":100,\"align\":\"center\"},{\"formatterParams\":{\"target\":\"_blank\"},\"title\":\"Measurements\",\"columns\":[{\"formatterParams\":{\"target\":\"_blank\"},\"title\":\"target\",\"field\":\"SET_TEMPERATURE-value\",\"formatter\":\"function(cell, formatterParams, onRendered){return cell.getValue()+'°C';}\",\"topCalc\":\"avg\",\"width\":100},{\"formatterParams\":{\"target\":\"_blank\",\"min\":10,\"max\":25,\"color\":[\"blue\",\"green\",\"red\"],\"legend\":\"function (value) {return '&nbsp;&nbsp;'+value+'°C';}\",\"legendColor\":\"#101010\",\"legendAlign\":\"left\"},\"title\":\"current\",\"field\":\"ACTUAL_TEMPERATURE-value\",\"formatter\":\"progress\",\"topCalc\":\"avg\",\"width\":100},{\"formatterParams\":{\"target\":\"_blank\",\"min\":0,\"max\":99,\"color\":[\"gray\",\"orange\",\"red\"],\"legend\":\"function (value) {return (value>0)? '&nbsp;&nbsp;'+value+' %' : '-';}\",\"legendColor\":\"#101010\",\"legendAlign\":\"center\"},\"title\":\"Valve\",\"field\":\"VALVE_STATE-value\",\"formatter\":\"progress\",\"topCalc\":\"max\",\"width\":100},{\"formatterParams\":{\"target\":\"_blank\",\"min\":1.5,\"max\":4.6,\"color\":[\"red\",\"orange\",\"green\"],\"legend\":\"function (value) {return value+' V';}\",\"legendColor\":\"#101010\",\"legendAlign\":\"center\"},\"title\":\"Batt\",\"field\":\"BATTERY_STATE-value\",\"formatter\":\"progress\",\"topCalc\":\"min\",\"width\":100}]},{\"formatterParams\":{\"target\":\"_blank\"},\"title\":\"Settings\",\"columns\":[{\"formatterParams\":{\"target\":\"_blank\",\"min\":0,\"max\":30,\"color\":[\"red\",\"orange\",\"green\"],\"legend\":\"function (value) {     if (value>0)         return \\\"<span style='color:#101010;'>\\\"+value+\\\" min</span>\\\";     else         return \\\"<span style='color:#A0A0A0;'>aus</span>\\\"; }\",\"legendColor\":\"#101010\",\"legendAlign\":\"center\"},\"title\":\"Boost\",\"field\":\"BOOST_STATE-value\",\"formatter\":\"progress\",\"width\":100},{\"formatterParams\":{\"target\":\"_blank\",\"allowEmpty\":true,\"allowTruthy\":true,\"tickElement\":\"<i class='fa fa-check' style='color:var(--nr-dashboard-pageTitlebarBackgroundColor)'></i>\",\"crossElement\":\"<i class='fa fa-times-circle' style='color:red;'></i>\"},\"title\":\"Auto\",\"field\":\"AUTO_MODE-value\",\"formatter\":\"tickCross\",\"width\":100,\"align\":\"center\"},{\"formatterParams\":{\"target\":\"_blank\"},\"title\":\"Mode\",\"field\":\"CONTROL_MODE-value\",\"formatter\":\"function(cell, formatterParams, onRendered){     var html=\\\"<i class=\\\\\\\"\\\";     switch(cell.getValue()) {         case 0: html+=\\\"fa fa-calendar-check-o\\\"; break;         case 1: html+=\\\"fa fa-hand-o-up\\\"; break;         case 2: html+=\\\"fa fa-suitcase\\\"; break;         case 3: html+=\\\"fa fa-spinner fa-spin fa-fw\\\"; break;     }     html+='\\\\\\\"></i>';     return html; }\",\"width\":100,\"align\":\"center\"}]}],\"layout\":\"fitColumns\",\"movableColumns\":true,\"groupBy\":\"\"},\"customHeight\":12}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":436,"y":2460,"wires":[["64210cf621fa0da5"]]},{"id":"bd5a8f10417763e5","type":"debug","z":"54efb553244c241f","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":749,"y":2460,"wires":[]},{"id":"64210cf621fa0da5","type":"ui_table","z":"54efb553244c241f","group":"51ce6aa1.620754","name":"Thermostats","order":1,"width":"20","height":"7","columns":[],"outputs":1,"cts":true,"x":599,"y":2460,"wires":[["bd5a8f10417763e5"]]},{"id":"51ce6aa1.620754","type":"ui_group","name":"ui_control","tab":"3b08fac0.8f06b6","order":1,"disp":true,"width":"22","collapse":false},{"id":"3b08fac0.8f06b6","type":"ui_tab","name":"Home","icon":"track_changes","order":1,"disabled":false,"hidden":false}]

Ah... tickElement... that makes more sense than the foreground color of the cell! I will give this a shot, thanks! And, this is done per column as well? Is there a way to apply these formatter parameters across all columns that are set to tickCross formatter?

Ok,, got the tick/cross element icon assignment working, and static color of course. Now for the bonus question? Can you sneak in a colorization that is more dynamic? Say I assigned a message part to a color...

msg.iconcolor='blue';

But slipping this message part into the JSON formatted text, does not seem to be rendered? Maybe I am doing it wrong?

"tickElement": "<i class='fa fa-check' style='color:var(--nr-dashboard-pageTitlebarBackgroundColor)'></i>",
"crossElement": "<i class='fa fa-times-circle' style='color:{msg.iconcolor}'></i>"

Or...

"tickElement": "<i class='fa fa-check' style='color:var(--nr-dashboard-pageTitlebarBackgroundColor)'></i>",
"crossElement": "<i class='fa fa-times-circle' style='color:{{iconcolor}}'></i>"

sure .. just switch in the Change node (the one that creates the ui_control msg)
instead of using { } JSON to use an Expression and then you can use jsonata with something like

"tickElement":"<i class='fa fa-check' style='color:var(--nr-dashboard-pageTitlebarBackgroundColor)'></i>",
"crossElement":"<i class='fa fa-times-circle' style='color:" & msg.iconcolor &";'></i>"

image

just saw you question .. i dont think there is a way to apply the formatting for many columns. because you need to specify the individual field which is linked to the data etc .. maybe with some advanced javascript map() code you can construct an array for multiple columns with the same formatting .. but if its not many columns maybe its better to just copy / paste the same lines a few times :wink:

Yeah, as I have been changing and testing things, the complexity of trying to setup common formatter parameters for a few columns (in my use case) is not worth the complexity that would result.

So expression variant accepts the variable references... but JSON is executed, or parsed rather just as HTML. I take it, it is the expression type that invokes the evaluation before the final HTML is rendered. I say this to remind me of this fact, and that anyone reading this will gain potential insight.

One more question... A bit of curve... colorize plain text? Since there does not seem to be an explicit 'element' the following did not work....

"textElement":"

"

Odd, Google tabulator references and did not seem to find a straight forward example of just colorizing plain text.

if its a style that you need to apply for all rows .. you can use
"rowFormatter": "function(row){ row.getElement().style.color = 'green'; }",

"tabulator": {
        ...
        "rowFormatter": "function(row){row.getElement().style.color = 'green'; //apply css change to row element}",
        "columns": [
            ...

if a column has it own specific formatting then that will be applied overriding the rowFormatter style

I just realized I asked the question wrong, this specific case is per cell, based on the value of the cell. I just realized as I was changing the code, that the entire row changed or the entire column changed.

I think this the direction I am going to need to follow...

{title:"Name", field:"name", 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 "Mr" + cell.getValue(); //return the contents of the cell;
},
}

The above is not specific to what I am trying to do, but I think is close, say if the value is 10, I want it to be green, 20 then yellow that type of idea.

@UnborN, yup... the trick is that I already have a row formatter that turns the entire row red, if an error resulted, so now I need to customize that formatter function to on error turn the row red, if not error then given the specific cell value, colorize it accordingly.

There is a post on the Forum about changing the cell text (or background) color based on its value

Yes, can you have multiple formatters? Meaning, the row formatter is separate from the per-cell formatter?

i did a quick test and it seems that if you have a rowFormatter and also in columns a custom cell formatter,
the cell formatter overwrites the more general rowFormatter for that cell .. which is a good thing

Ah, then that is easy to deal with in my use case. I will only have a cell value update when the row is not colorized. So, either the entire row is red... an error. Or the cell in the row has a value, and it is colorized as applicable. Or I just set a flag that error has happened, if so, the cell formatter knows to take action accordingly. I will play around with it, and see what I can do. Pretty much whatever renders last wins of course.

1 Like

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