I spent a bit of time stepping back to contemplate how to couple messages and state between node-red and the UI.
Node-red is about messages and their flow is represented visually and the graph is static. State, especially persistent state, is secondary and a bit more cumbersome to manage, and not really a first-class object in the admin UI.
Modern web UIs are reactive, which means they couple the state of variables with the state of visual elements. The state is directly represented in terms of variables in the code whereas the flow of data is a side-effect of picking the same name in two or more places.
When building a UI for node-red we're trying to couple these two worlds and that's not simple in part due to this mismatch. Another way to express the mismatch is that a UI represents both state and changes (i.e. messages). For example, if the UI shows a switch for the light in your room, when you pull up the UI you want the switch to show the state of the light. And when you toggle the switch you want the UI to send a message to cause a change and then to reflect the new state.
Let me try to expand the light switch example assuming the light is controlled by sending an MQTT message or HTTP request. We have the state of the light in three places:
- the actual HW light controller to which we send the message
- in node-red, probably a persistent context variable
- in the UI in a reactive variable from where it propagates to the DOM
In terms of functionality what we need is:
- when a UI client connects, transfer the light's state from the persistent context to the UI's reactive variable
- when the user actuates the switch in the UI, send a message to NR to update the persistent context value and to output a command to the light
- optionally, at NR start-up, instead of relying on persistent state it may be possible to query the light bulb controller for the current state
- in addition, we'll want to provide an input so other nodes can change the light state, for example, something that turns all lights off at midnight
What struck me is that when I started thinking about the distributed state I could stop thinking about the umpteen different UI widgets in node-red. Node-red doesn't have to have switches, buttons, text fields, drop-downs and all that. It can, that's one approach embodied in the current dashboard, but it's not the only approach.
A different approach is for node-red to have a node that couples state in node-red with state in the UI's reactive variables. From the node-red perspective the input to the ui-state node changes the state and its output sends a message whenever the state changes. Underneath, the ui-state node communicates with any browser to reflect the state into a "reactive variable".
The UI can then be virtually ignorant of node-red. It needs a module that connects to node-red and maintains the reactive variables but aside from that, the UI components really don't care. The variables could just as well be updated via database queries to a rest service.
Something all this does is decouple the state in node-red from the visual representation in the UI. Node-red doesn't care whether the light's state is represented by an icon, by a switch, by a text string, or by anything else. It also doesn't care whether the state is changed using a button, a slider, a switch, a drop-down, etc. All it needs to do is play its part in coupling its state with the state variables in the UI.
In terms of building the UI, it doesn't have to be a custom piece of code. There could be a visual designer that drops web components onto a canvas, couple them with state variables, and lets the user visually arrange the whole thing. The designer could be completely separate from node-red or it could be a part of the node-red admin UI. It doesn't matter. Maybe there's a UI designer project out there that can be used as-is...
I don't think this different approach replaces the current dashboard. Some people will prefer to have everything in the node-red admin UI and to connect all the parts with wires. (The trade-off being that the connection between a node and its visual element position is rather cumbersome.)
What is really attractive to me is the decoupling though. It means every web component doesn't also have to have a node with logic to massage messages plus a configuration panel for the admin UI. We "just" need one or a couple of nodes in NR to reflect state and web components that are appropriately crafted. Plus probably a designer UI to assemble the web components for those that prefer that approach.
(BTW, I'm not trying to say that I just invented all this, not at all. It's been said before and uibuilder does a lot of it. I'm just trying to formulate the big picture.)