Re-rendered dial gauges on widget add / remove
Description
Problem
UI-Gauge (dial with needle) was loosing the track of its position when adding and removing widget into the same group.
Solution
Re-rendered the dial gauges upon adding / removing widgets in the same group as the same way tracked and re-rendered dial gauges on dynamic property changes
https://github.com/user-attachments/assets/e77bd56c-0fe0-428d-9d69-961ed0f2dfd9
Related Issue(s)
ui-gauge 2.0 1.17.1 - The needle loses track of it's position
This doesn't need documentation or E2E test update
Checklist
- [x] I have read the contribution guidelines
- [ ] Suitable unit/system level tests have been added and they pass
- [ ] Documentation has been updated
- [ ] Upgrade instructions
- [ ] Configuration details
- [ ] Concepts
- [ ] Changes
flowforge.yml?- [ ] Issue/PR raised on
FlowFuse/helmto update ConfigMap Template - [ ] Issue/PR raised on
FlowFuse/CloudProjectto update values for Staging/Production
- [ ] Issue/PR raised on
Labels
- [ ] Includes a DB migration? -> add the
area:migrationlabel
I've tried to re-create the problem in Chrome, and I couldn't. The underlying issue only seems to exist in Safari, where, even with these changes, the problem persists:
I've tried to re-create the problem in Chrome, and I couldn't. The underlying issue only seems to exist in Safari, where, even with these changes, the problem persists:
@joepavitt I noticed the needle problem in Chrome too. I just used the same flow given in the original issue and added a new gauge in the middle. And tried by enabling and disabling the gauge node using its NR edit window.
Luckily the units didn't get collided with others
The dashboard 2.0 flow I used is below 👇
[{"id":"8bc24fdfe79d7aa2","type":"ui-gauge","z":"80a7b66be7ea4735","name":"ampere","group":"f9fe8211d40a5300","order":8,"width":"3","height":"4","gtype":"gauge-34","gstyle":"needle","title":"ampere","units":"A","icon":"","prefix":"","suffix":"","segments":[{"from":"0","color":"#00f900"},{"from":"77","color":"#ff9300"},{"from":"100","color":"#ff2600"},{"from":"120","color":"#ff2600"}],"min":"0","max":"120","sizeThickness":16,"sizeGap":4,"sizeKeyThickness":8,"styleRounded":true,"styleGlow":false,"className":"","x":980,"y":400,"wires":[]},{"id":"fbee797bb24fbc0b","type":"ui-gauge","z":"80a7b66be7ea4735","name":"batteri amps","group":"f9fe8211d40a5300","order":3,"width":"3","height":"4","gtype":"gauge-34","gstyle":"needle","title":"ampere","units":"A","icon":"","prefix":"","suffix":"","segments":[{"from":"-120","color":"#ff9300"},{"from":"-110","color":"#00f900"},{"from":"0","color":"#00f900"},{"from":"110","color":"#00f900"},{"from":"111","color":"#ff9300"},{"from":"120","color":"#ff9300"}],"min":"-120","max":"120","sizeThickness":16,"sizeGap":4,"sizeKeyThickness":8,"styleRounded":true,"styleGlow":false,"className":"","x":990,"y":360,"wires":[]},{"id":"b12a10fe23e4b783","type":"ui-gauge","z":"80a7b66be7ea4735","name":"batt power watts","group":"f9fe8211d40a5300","order":9,"width":"3","height":"4","gtype":"gauge-34","gstyle":"rounded","title":"watt","units":"W","icon":"","prefix":"","suffix":"","segments":[{"from":"-3000","color":"#ff9300"},{"from":"-2400","color":"#00f900"},{"from":"0","color":"#00f900"},{"from":"2500","color":"#ff2600"},{"from":"3000","color":"#ff2600"}],"min":"-3000","max":"3000","sizeThickness":16,"sizeGap":4,"sizeKeyThickness":8,"styleRounded":true,"styleGlow":false,"className":"","x":1010,"y":440,"wires":[]},{"id":"cc05114576d9df0b","type":"ui-gauge","z":"80a7b66be7ea4735","name":"batt power +/-","group":"f9fe8211d40a5300","order":1,"width":"3","height":"4","gtype":"gauge-34","gstyle":"needle","title":"batt power +/-","units":"kW","icon":"","prefix":"","suffix":"","segments":[{"from":"-4","color":"#ff9300"},{"from":"","color":"#000000"},{"from":"-3.5","color":"#3a88fe"},{"from":"0","color":"#3a88fe"},{"from":"3.5","color":"#3a88fe"},{"from":"3.6","color":"#ff9300"},{"from":"4","color":"#ff9300"}],"min":"-4","max":"4","sizeThickness":16,"sizeGap":4,"sizeKeyThickness":8,"styleRounded":true,"styleGlow":false,"className":"","x":1000,"y":220,"wires":[]},{"id":"97e42e2a59246509","type":"ui-gauge","z":"80a7b66be7ea4735","name":"batteri volts","group":"f9fe8211d40a5300","order":4,"width":"3","height":"4","gtype":"gauge-34","gstyle":"needle","title":"volt","units":"V","icon":"","prefix":"","suffix":"","segments":[{"from":"10","color":"#ff2600"},{"from":"11.1","color":"#ff9300"},{"from":"11.8","color":"#5cd65c"},{"from":"14.3","color":"#ff2600"},{"from":"15","color":"#ff2600"}],"min":"10","max":"15","sizeThickness":16,"sizeGap":4,"sizeKeyThickness":8,"styleRounded":true,"styleGlow":false,"className":"","x":990,"y":260,"wires":[]},{"id":"74b4b2f72261eb22","type":"ui-gauge","z":"80a7b66be7ea4735","name":"batteri temperatur","group":"f9fe8211d40a5300","order":7,"width":"3","height":"4","gtype":"gauge-34","gstyle":"needle","title":"temp","units":"°C","icon":"","prefix":"","suffix":"","segments":[{"from":"-40","color":"#ff9300"},{"from":"5","color":"#ff9300"},{"from":"6","color":"#00f900"},{"from":"31","color":"#ff9300"},{"from":"40","color":"#ff2600"}],"min":"-40","max":"40","sizeThickness":16,"sizeGap":4,"sizeKeyThickness":8,"styleRounded":true,"styleGlow":false,"className":"","x":1010,"y":300,"wires":[]},{"id":"85fef5c0c179d8f1","type":"inject","z":"80a7b66be7ea4735","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"3","payloadType":"num","x":750,"y":440,"wires":[["fbee797bb24fbc0b","8bc24fdfe79d7aa2","b12a10fe23e4b783","cc05114576d9df0b","97e42e2a59246509","74b4b2f72261eb22","509686d704616771","349b7f3aca90ca05","3c75fc9fb80c159b"]]},{"id":"509686d704616771","type":"ui-gauge","z":"80a7b66be7ea4735","name":"batteri amps","group":"f9fe8211d40a5300","order":5,"width":"3","height":"4","gtype":"gauge-34","gstyle":"needle","title":"ampere","units":"A","icon":"","prefix":"","suffix":"","segments":[{"from":"-120","color":"#ff9300"},{"from":"-110","color":"#00f900"},{"from":"0","color":"#00f900"},{"from":"110","color":"#00f900"},{"from":"111","color":"#ff9300"},{"from":"120","color":"#ff9300"}],"min":"-120","max":"120","sizeThickness":16,"sizeGap":4,"sizeKeyThickness":8,"styleRounded":true,"styleGlow":false,"className":"","x":990,"y":500,"wires":[]},{"id":"349b7f3aca90ca05","type":"ui-gauge","z":"80a7b66be7ea4735","name":"batt power watts","group":"f9fe8211d40a5300","order":6,"width":"3","height":"4","gtype":"gauge-34","gstyle":"rounded","title":"watt","units":"W","icon":"","prefix":"","suffix":"","segments":[{"from":"-3000","color":"#ff9300"},{"from":"-2400","color":"#00f900"},{"from":"0","color":"#00f900"},{"from":"2500","color":"#ff2600"},{"from":"3000","color":"#ff2600"}],"min":"-3000","max":"3000","sizeThickness":16,"sizeGap":4,"sizeKeyThickness":8,"styleRounded":true,"styleGlow":false,"className":"","x":1010,"y":560,"wires":[]},{"id":"c83113e976a0c20b","type":"ui-slider","z":"80a7b66be7ea4735","group":"f9fe8211d40a5300","name":"","label":"slider","tooltip":"","order":10,"width":"6","height":"3","passthru":false,"outs":"all","topic":"topic","topicType":"msg","thumbLabel":"always","showTicks":"always","min":0,"max":"100","step":1,"className":"","iconPrepend":"","iconAppend":"","color":"","colorTrack":"","colorThumb":"","x":730,"y":360,"wires":[["cc05114576d9df0b","97e42e2a59246509","74b4b2f72261eb22","fbee797bb24fbc0b","8bc24fdfe79d7aa2","509686d704616771","b12a10fe23e4b783","349b7f3aca90ca05","3c75fc9fb80c159b"]]},{"id":"3c75fc9fb80c159b","type":"ui-gauge","z":"80a7b66be7ea4735","name":"New","group":"f9fe8211d40a5300","order":2,"width":"3","height":"6","gtype":"gauge-half","gstyle":"needle","title":"New gauge","units":"units","icon":"","prefix":"","suffix":"","segments":[{"from":"0","color":"#5cd65c"},{"from":"4","color":"#ffc800"},{"from":"7","color":"#ea5353"}],"min":0,"max":10,"sizeThickness":16,"sizeGap":4,"sizeKeyThickness":8,"styleRounded":true,"styleGlow":false,"className":"","x":970,"y":620,"wires":[]},{"id":"f9fe8211d40a5300","type":"ui-group","name":"g git 1","page":"e3f48fc6daf125cf","width":"6","height":"1","order":1,"showTitle":true,"className":"","visible":"true","disabled":"false"},{"id":"e3f48fc6daf125cf","type":"ui-page","name":"p git 1","ui":"a171c8195c1b8e57","path":"/git1","icon":"home","layout":"grid","theme":"a9af1506409fba49","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":2,"className":"","visible":true,"disabled":false},{"id":"a171c8195c1b8e57","type":"ui-base","name":"My Dashboard","path":"/dashboard","includeClientData":true,"acceptsClientConfig":["ui-control","ui-chart","ui-form","ui-file-input","ui-button","ui-button-group","ui-dropdown","ui-slider","ui-switch","ui-text","ui-markdown","ui-notification","ui-template","ui-table"],"showPathInSidebar":false,"showPageTitle":true,"navigationStyle":"icon","titleBarStyle":"default"},{"id":"a9af1506409fba49","type":"ui-theme","name":"black and grey","colors":{"surface":"#000000","primary":"#919191","bgPage":"#000000","groupBg":"#000000","groupOutline":"#000000"},"sizes":{"pagePadding":"2px","groupGap":"2px","groupBorderRadius":"2px","widgetGap":"3px","density":"compact"}}]
I will check in the Safari too
Rather than watching the widgets array, if the issue is caused by the container of the gauge re-sizing when others are added/removed, why not put a ResizeObserver on the gauge itself, and then re-render in cases when the size changes?
Rather than watching the
widgetsarray, if the issue is caused by the container of the gauge re-sizing when others are added/removed, why not put aResizeObserveron the gauge itself, and then re-render in cases when the size changes?
As per the offline discussion with @joepavitt I've re-rendered gauge dials on resize and considered.
As I noticed, Safari is not properly adjusting the grid row heights, causing the layout to appear cluttered. Unlike in Chrome, where the gauges fit neatly, Safari seems to mishandle the row sizing. This inconsistency affects the display and usability of the grid-based interface.
Due to the observed issue, I applied a fix here. The main change I made was ensuring the component calculates the minimum dimension between width and height using Math.min(clientWidth, clientHeight). This allows the component to adjust its size dynamically based on the available space.
This is ready for review
Font Size
The font size of the value has broken and is rendering too small.
### Problem Not Fixed This has also still, after my fourth review, not fixed the underlying problem reported for Safari, where the needle doesn't correctly align to the gauge
![]()
@joepavitt Seems like it's a bit strange behaviour, This is what I'm seeing when comparing on Chrome and Safari side by side
Screenshot
Screen recording https://github.com/user-attachments/assets/55c430b2-2853-45e5-86f5-d3988d1ece08
Managed to establish this is a Safari version problem (I'm running v14, Gayan on newer). However, we also have an opportunity here to fix https://github.com/FlowFuse/node-red-dashboard/issues/560
The resize event should nt monitor window, but instead the gauge.
Managed to establish this is a Safari version problem (I'm running v14, Gayan on newer). However, we also have an opportunity here to fix #560
The
resizeevent should not monitorwindow, but instead thegauge.
@joepavitt as discussed I've applied the fix using ResizeObserver with these 2 commits https://github.com/FlowFuse/node-red-dashboard/pull/1353/commits/91ee77e914cbf19413bd5701f0458a94d8855e47 https://github.com/FlowFuse/node-red-dashboard/pull/1353/commits/8ee9ab42cfbaa713a789ec19882319de6a37ed49
Description has been updated with the solution and the screen recording of the behaviour after the fix
Also for the issue #560 I will check and verify other widgets separately as the reporter of the issue mentioned "Any widget (like ui_gauge) using window resize event"
This all looks good. Thanks for the video demonstration.
I am however a little concerned about then there are many gauges on a lower powered device. The resize observer runs very fast. e.g:
Perhaps a follow up issue to throttle the observer just enough to give a little breathing space - perhaps limit updates upon resize to 1 in every 100ms?
Again, happy for that to be a follow up task - so approving for now.
@Steve-Mcl A followup task has been raised as discussed https://github.com/FlowFuse/node-red-dashboard/issues/1376
### Problem Not Fixed
This has also still, after my fourth review, not fixed the underlying problem reported for Safari, where the needle doesn't correctly align to the gauge