Dashboard 2 with gauge fixed format display

Unfortunately the thread cannot be reopend: https://discourse.nodered.org/t/gauge-w-fixed-format-display - or I do not know how.

Since the gauge can perform strings, the problem to have a digit as decimal number even if the number has no decimal fraction has been solved to have a comparable functionality with angular notation to display the number always with one digit as decimal fraction (i.e. 19.0)

In the old dashboard this could be achieved by: {{value| number:1}}

After I read the description of the gauge:

I had the hope, that all numeric JSONATA functions can be used, including formatNumber.

It seems to work with the resulting string, when the number can be converted back, but not when you replace the decimal point with a decimal comma.

So this JSONATA expression seems to work:

$formatNumber(payload, "#,#0.0")	

however this JSONATA expression not:

$formatNumber(payload, "#.##0,0", {'decimal-separator':',', 'grouping-separator':'.'})

So my question is: Is there a way to separate the output format of the value representation from the internal value of the gauge?

Here is the export of what I have tried:

[{"id":"e8d7609c5486c528","type":"inject","z":"038f5e3bc8be41ec","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"18.04","payloadType":"num","x":230,"y":100,"wires":[["e8353a7ab039d70c","c0c47b5128b2b549","93a9b84f824eca73","b6b2798bb5faec29"]]},{"id":"e8353a7ab039d70c","type":"change","z":"038f5e3bc8be41ec","name":"Number Format","rules":[{"t":"set","p":"payload","pt":"msg","to":"$formatNumber(payload, \"#,#0.0\")\t","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":480,"y":100,"wires":[["bc1a672ec27702c0"]]},{"id":"bc1a672ec27702c0","type":"ui-gauge","z":"038f5e3bc8be41ec","name":"","group":"c9e960fa98fc444e","order":3,"value":"payload","valueType":"msg","width":"3","height":"3","gtype":"gauge-half","gstyle":"needle","title":"Temperatur (String dot)","alwaysShowTitle":false,"floatingTitlePosition":"top-left","units":"°C","icon":"","prefix":"","suffix":"","segments":[{"from":"15","color":"#5cd65c","text":"","textType":"label"},{"from":"20","color":"#ffc800","text":"","textType":"label"},{"from":"25","color":"#ea5353","text":"","textType":"label"}],"min":"15","max":"30","sizeThickness":16,"sizeGap":4,"sizeKeyThickness":8,"styleRounded":true,"styleGlow":false,"className":"","x":730,"y":100,"wires":[[]]},{"id":"c0c47b5128b2b549","type":"change","z":"038f5e3bc8be41ec","name":"Number Format","rules":[{"t":"set","p":"payload","pt":"msg","to":"$formatNumber(payload, \"#.##0,0\", {'decimal-separator':',', 'grouping-separator':'.'})","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":480,"y":160,"wires":[["cb7c72ee1c082d60","821fcc04d61efae6"]]},{"id":"cb7c72ee1c082d60","type":"ui-gauge","z":"038f5e3bc8be41ec","name":"","group":"c9e960fa98fc444e","order":4,"value":"payload","valueType":"msg","width":"3","height":"3","gtype":"gauge-half","gstyle":"needle","title":"Temperatur (String Comma)","alwaysShowTitle":false,"floatingTitlePosition":"top-left","units":"°C","icon":"","prefix":"","suffix":"","segments":[{"from":"15","color":"#5cd65c","text":"","textType":"label"},{"from":"20","color":"#ffc800","text":"","textType":"label"},{"from":"25","color":"#ea5353","text":"","textType":"label"}],"min":"15","max":"30","sizeThickness":16,"sizeGap":4,"sizeKeyThickness":8,"styleRounded":true,"styleGlow":false,"className":"","x":740,"y":160,"wires":[[]]},{"id":"821fcc04d61efae6","type":"debug","z":"038f5e3bc8be41ec","name":"Number Format","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":700,"y":200,"wires":[]},{"id":"93a9b84f824eca73","type":"ui-gauge","z":"038f5e3bc8be41ec","name":"","group":"c9e960fa98fc444e","order":1,"value":"$formatNumber(payload, \"#,#0.0\")\t","valueType":"jsonata","width":"3","height":"3","gtype":"gauge-half","gstyle":"needle","title":"Temperatur (JSONATA w/ dot)","alwaysShowTitle":false,"floatingTitlePosition":"top-left","units":"°C","icon":"","prefix":"","suffix":"","segments":[{"from":"15","color":"#5cd65c","text":"","textType":"label"},{"from":"20","color":"#ffc800","text":"","textType":"label"},{"from":"25","color":"#ea5353","text":"","textType":"label"}],"min":"15","max":"30","sizeThickness":16,"sizeGap":4,"sizeKeyThickness":8,"styleRounded":true,"styleGlow":false,"className":"","x":510,"y":260,"wires":[[]]},{"id":"b6b2798bb5faec29","type":"ui-gauge","z":"038f5e3bc8be41ec","name":"","group":"c9e960fa98fc444e","order":2,"value":"$formatNumber(payload, \"#.##0,0\", {'decimal-separator':',', 'grouping-separator':'.'})","valueType":"jsonata","width":"3","height":"3","gtype":"gauge-half","gstyle":"needle","title":"Temperatur (JSONATA w/ comma)","alwaysShowTitle":false,"floatingTitlePosition":"top-left","units":"°C","icon":"","prefix":"","suffix":"","segments":[{"from":"15","color":"#5cd65c","text":"","textType":"label"},{"from":"20","color":"#ffc800","text":"","textType":"label"},{"from":"25","color":"#ea5353","text":"","textType":"label"}],"min":"15","max":"30","sizeThickness":16,"sizeGap":4,"sizeKeyThickness":8,"styleRounded":true,"styleGlow":false,"className":"","x":520,"y":320,"wires":[[]]},{"id":"c9e960fa98fc444e","type":"ui-group","name":"Wohnzimmer","page":"51a0134b042c50c1","width":3,"height":1,"order":1,"showTitle":true,"className":"","visible":"true","disabled":"false","groupType":"default"},{"id":"51a0134b042c50c1","type":"ui-page","name":"Heizung","ui":"56102368e4635988","path":"/heizung","icon":"heat-wave","layout":"grid","theme":"9e975ecc842294ee","breakpoints":[{"name":"Default","px":"0","cols":"3"},{"name":"Tablet","px":"576","cols":"6"},{"name":"Small Desktop","px":"768","cols":"9"},{"name":"Desktop","px":"1024","cols":"12"}],"order":6,"className":"","visible":"true","disabled":"false"},{"id":"56102368e4635988","type":"ui-base","name":"dashboard","path":"/dashboard","includeClientData":true,"acceptsClientConfig":["ui-notification","ui-control"],"showPathInSidebar":false,"headerContent":"page","titleBarStyle":"default","showReconnectNotification":true,"notificationDisplayTime":5,"showDisconnectNotification":true,"allowInstall":true},{"id":"9e975ecc842294ee","type":"ui-theme","name":"Dark Theme","colors":{"surface":"#097479","primary":"#0eb8c0","bgPage":"#111111","groupBg":"#333333","groupOutline":"#555555"},"sizes":{"pagePadding":"12px","groupGap":"12px","groupBorderRadius":"4px","widgetGap":"12px","density":"default"}},{"id":"64e74b77ebc260be","type":"global-config","env":[],"modules":{"@flowfuse/node-red-dashboard":"1.29.0"}}]

TLDR

The third parameter for formatNumber is not available until Node-red updates it's embedded JSONata evaluation layer.

Details

According to chatgpt:
  • Node-red v4.1.0 lists jsonata 2.0.6 as a dependency in @node-red/util
  • The third parameter for $formatNumber() is supported by jsonata 1.8+

Thus you might expect that a jsonata expression

$formatNumber(98765.4320, "#,##0.00", {
  "decimalSeparator": ",",
  "groupSeparator": " "
})

would be output as "98 765,43", but what I get is "98,765.43"
(I guess this formatting might also be influenced by locale settings)

Chatgpt explains the anomaly thusly:

Node-RED includes JSONata 2.0.6 as a dependency in @node-red/util.

However, the Change node [and the Jsonata typed-input more generally] 
uses a sandboxed evaluator of JSONata inside Node-RED’s runtime engine.

That evaluator does not pass through the optional “options” object 
to $formatNumber(), so only the two-argument form works.

| Feature                                   | Supported in Node-RED 4.1.0 Change Node? |
| ----------------------------------------- | ---------------------------------------- |
| `$formatNumber(number, picture)`          | ✅ Yes                                    |
| `$formatNumber(number, picture, options)` | ❌ Ignored (as of 4.1.0)                  |
| `$replace()` workaround                   | ✅ Works perfectly                        |

And she offers a work-around

Until Node-RED updates its embedded JSONata evaluation layer, 
you can emulate the desired formatting with $replace() calls:

$replace(
  $replace(
    $formatNumber(payload, "#,##0.00"),
    ",", " "
  ),
  ".", ","
)

In my opinion the JSONATA implementation already works perfect with spaces, comma or dots.

The only thing you need to take care is that the picture string does contain the same characters as specified in the 3rd parameter. Your example with the space as thousand separator must look like:

$formatNumber(payload, "# ##0,0", {'decimal-separator':',', 'grouping-separator':' '})
[{"id":"1a6a5249c4cd916e","type":"debug","z":"038f5e3bc8be41ec","name":"number format - DE","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":810,"y":720,"wires":[]},{"id":"c0c47b5128b2b549","type":"change","z":"038f5e3bc8be41ec","name":"Number Format","rules":[{"t":"set","p":"payload","pt":"msg","to":"$formatNumber(payload, \"#.##0,0\", {'decimal-separator':',', 'grouping-separator':'.'})","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":600,"y":720,"wires":[["1a6a5249c4cd916e"]]},{"id":"2602f1a023bd39a7","type":"inject","z":"038f5e3bc8be41ec","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"12168.02","payloadType":"num","x":360,"y":780,"wires":[["c0c47b5128b2b549","37c49544f3b1a824","58f2c28ddd7d4f31"]]},{"id":"1e9e227bafda69fe","type":"debug","z":"038f5e3bc8be41ec","name":"number format - US","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":810,"y":780,"wires":[]},{"id":"37c49544f3b1a824","type":"change","z":"038f5e3bc8be41ec","name":"Number Format","rules":[{"t":"set","p":"payload","pt":"msg","to":"$formatNumber(payload, \"#,##0.0\", {'decimal-separator':'.', 'grouping-separator':','})","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":600,"y":780,"wires":[["1e9e227bafda69fe"]]},{"id":"58f2c28ddd7d4f31","type":"change","z":"038f5e3bc8be41ec","name":"Number Format","rules":[{"t":"set","p":"payload","pt":"msg","to":"$formatNumber(payload, \"# ##0,0\", {'decimal-separator':',', 'grouping-separator':' '})","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":600,"y":840,"wires":[["344d96918ac9c410"]]},{"id":"344d96918ac9c410","type":"debug","z":"038f5e3bc8be41ec","name":"number format - space","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":820,"y":840,"wires":[]}]

So it seems to be a misunderstanding. I have no problems with JSONATA - but when I use the formatNumber function in a gauge with a comma as decimal separator - it is no longer recognized as number.

Yes, I clearly misunderstood this as the nub of your problem. I apologise.

And between chatgpt and myself we seem to have got confused over whether the third parameter is ignored. From your example above, apparently it is not.