Uibuilder: to subscribe or not to subscribe?

Well, sometimes you have to do it all wrong and come full circle :slight_smile:

I went back to almost what @TotallyInformation has: messages contain property values that are just pushed into the components. I had changed this to a message dispatch where components contain a handler method that is called with the message. I had the linkage using the same ref= property as @TotallyInformation's examples have.

The reason I went back is that in Vue updating values should happen through properties and through the general "reactivity". Sending messages around or calling handler methods just goes around this and thus ends up clashing. In @TotallyInformation's examples the clash comes from vue complaining that props are being updated directly. Going back to using the reactivity mechanism properly reduced my code size significantly, everything is now so simple.

So what I ended up with is:

  • the app main (index.js) contains a nr data, which holds all data that has come in from node-red (hence "nr").
  • when a message comes in, it must have a topic and a payload, the message is simply stored as nr[msg.topic] = msg.payload (technically I have to use Vue.set, but that's insignificant).
  • the page html instantiates components and for components that need to get data from node-red the appropriate portions of the nr data are bound to the component's props using the standard Vue v-bind

And that's it, couldn't be simpler!

simple example

Simple example: a stat component that shows a title, a value, and a units string.

  • the component has 3 properties: title, unit, value
  • the page html instantiates the component and binds the value for updating like this:
    <stat title="bedroom" unit="°F" v-bind:value="nr.bedroom_temperature"></stat>
  • the NR flow sends a message to the page to update the temperature like this:
    { topic: "bedroom_temperature", payload: 77 }
  • the result:
    image

array example

A more complex example has an array component that expects an array of title/unit/value objects and generates an array of stat components for all those values:

  • the array component has some properties, including array (in this example there's no other property, but there could be in the future)
  • the page html instantiates the array component and provides the template for the stat component as follows:
    <array v-bind="nr.temperature_array">
      <template v-slot:default="slotProps">
        <stat v-bind="slotProps"></stat>
      </template>
    </array>

the v-binds used here bind all properties of the component, as opposed to the v-bind:value used above that only bound the value property

  • the message sent from node-red looks as follows:
    { topic: "temperature_array",
      payload: {
        array: [
          { title: "bedroom", unit: "°F", value: "75" },
          { title: "living room", unit: "°F", value: "72" },
          ...,
    ]}}

In this case, the array property of the message payload updates the property of the same name in the array component.


I uploaded the whole thing I have to GitHub - tve/uibuilder-test: Node-Red Test Dashboard using uibuilder in case someone wants to take a peek...

2 Likes