Dashboard 2 radio group

trying to roll my own radio group in DB2 and cannot seem to quite get the job done. Between Dr. Google and ChatGPT I think I'm close but I get no output from my node. any help appreciated.

<template>
  <v-app>
    <v-container>
      <v-row>
        <v-col cols="12">
          <h2>Choose your favorite color:</h2>
          
          <v-radio-group v-model="selectedColor">
            <v-radio label="Red" value="red"></v-radio>
            <v-radio label="Blue" value="blue"></v-radio>
            <v-radio label="Green" value="green"></v-radio>
          </v-radio-group>
          
          <p>You selected: {{ selectedColor }}</p>
        </v-col>
      </v-row>
    </v-container>
  </v-app>
</template>

<script>
export default {
  data() {
    return {
      selectedColor: '' // This will store the selected color
    }
  },

  watch: {
    msg: {
      deep: true,
      handler(newVal) {
        if (selectedColor === 'red') {
          this.Red()
        }
        if (newVal.payload === 'blue') {
          this.Blue()
        }
        if (newVal.payload === 'green') {
          this.Green()
        }
      },
    },
  },

  methods: {
    Red() {
      this.send({ topic: 'Power', payload: 'power' })
    },

    Blue: function () {
      this.send({ topic: 'Minus', payload: '1' })
    },

    Green: function () {
      this.send({ topic: 'Plus', payload: '1' })
    },
  },
}
</script>

<style>
/* Add any custom styles here */
</style>

Try msg: function () {

forgive my ignorance but where does that go?

<template>
  <v-app>
    <v-container>
      <v-row>
        <v-col cols="12">
          <h2>Choose your favorite color:</h2>
          
          <v-radio-group v-model="selectedColor">
            <v-radio label="Red" value="red"></v-radio>
            <v-radio label="Blue" value="blue"></v-radio>
            <v-radio label="Green" value="green"></v-radio>
          </v-radio-group>
          
          <p>You selected: {{ selectedColor }}</p>
        </v-col>
      </v-row>
    </v-container>
  </v-app>
</template>

<script>
export default {
  data() {
    return {
      selectedColor: '' // This will store the selected color
    }
  },

  watch: {
    msg: function () {
      deep: true,
      handler(newVal) {
        if (selectedColor === 'red') {
          this.Red()
        }
        if (newVal.payload === 'blue') {
          this.Blue()
        }
        if (newVal.payload === 'green') {
          this.Green()
        }
      },
    },
  },

  methods: {
    Red() {
      this.send({ topic: 'Power', payload: 'power' })
    },

    Blue: function () {
      this.send({ topic: 'Minus', payload: '1' })
    },

    Green: function () {
      this.send({ topic: 'Plus', payload: '1' })
    },
  },
}
</script>

<style>
/* Add any custom styles here */
</style>

when I put it this way the entire block is blank

You forgot this. as in this.selectedColor

When testing, open the developer tool console in the browser and you may get clues about the problem.

  watch: {
    msg:{
      deep: true,
      handler(newVal) {
        if (this.selectedColor === 'red') {
                this.send({ topic: 'Power', payload: 'power' })
        }
        if (this.selectedColor === 'blue') {
          this.Blue()
        }
        if (this.selectedColor === 'green') {
          this.Green()
        }
      },
    },
  },

tried this and still no output, sorry for being thick guys

I think you can simplify the code;

<template>
    <v-app>
        <v-container>
            <v-row>
                <v-col cols="12">
                    <h2>Choose your favorite color:</h2>
                    <v-radio-group v-model="selectedColor">
                        <v-radio v-for="radio in radioGroupItems" :label="radio.label"
                            :value="radio.label.toLowerCase()" @click="send(radio)">
                        </v-radio>
                    </v-radio-group>
                    <p>You selected: {{ selectedColor }}</p>
                </v-col>
            </v-row>
        </v-container>
    </v-app>
</template>

<script>
    export default {
  data() {
    return {
      selectedColor:null,
      radioGroupItems :[
        {label:'Red',topic:'Power',payload:'power'},
        {label:'Blue',topic:'Minus',payload:1},
        {label:'Green',topic:'Plus',payload:1}
        ],
    }
  }
}
</script>
<style>
    /* Add any custom styles here */
</style>

The point of these frameworks is that they are reactive, meaning within the template tag, it is aware of all states of all objects and their properties and you can bind any property dynamically to attributes by simply adding a : in front of the attribute, you don't have to track their state.

1 Like

thanks for the code and the explanation, much appreciated

If I may, one more thing, could you please show me how to set the radio button programmatically with an incoming message?
Thanks

You have two options detailed here.

Option 1 may be your best option here, as it already extends the handler you have in place. When the msg changes (which will be because of an incoming msg) you can put relevant functionality there, and check against newVal (which will be the new, incoming msg object) for any relevant properties you're looking for, and react accordingly.

I get to here

<<template>
    <v-app>
        <v-container>
            <v-row>
                <v-col cols="12">
                    <h2>Choose your favorite color:</h2>
                    <v-radio-group v-model="selectedColor">
                        <v-radio v-for="radio in radioGroupItems" :label="radio.label"
                            :value="radio.label.toLowerCase()" @click="send(radio)">
                        </v-radio>
                    </v-radio-group>
                    <p>You selected: {{ selectedColor }}</p>
                </v-col>
            </v-row>
        </v-container>
    </v-app>
</template>


<script>
    export default {
  data() {
    return {
      selectedColor:null,
      radioGroupItems :[
        {label:'Red',topic:'Power',payload:'power'},
        {label:'Blue',topic:'Minus',payload:1},
        {label:'Green',topic:'Plus',payload:1}
        ],
    }
  },


    watch: {
      msg: {
        deep: true,
        handler(newVal) {
          if (newVal.payload === 'option1') {
            this.Power_On()
          }
          if (newVal.payload === 'stop') {
            this.Power_Off()
          }
          if (newVal.payload === 'next') {
            this.Power_Next()
          }
        },
      },
    },

    methods: {

      Power_Off: function () {
        this.send({ topic: 'Power', payload: 'Off' })
      },

      Power_On: function () {
        this.send({ topic: 'Power', payload: 'On' })
      },

      Power_Next: function () {
        this.send({ topic: 'Power', payload: 'Next' })
      },
    },
  }
</script>

and I get an output but the button isn't selected on the dashboard

If the radio button changes, it will send the message, so when you inject a change into node, it will send the message, this can potentially create an infinite loop.

In the methods you are changing the payloads from minus/plus/power to On/Off/Next, is this intentional ?

You could do something like this (not tested)

handler(m) {
   const findColor = this.radioGroupItems.find(x=>x.label == m?.payload)
   if(findColor){
      this.selectedColor = m.payload
   }
}

Then you can remove the methods

The incoming payload should only contain the color name (matching the labels within radioGroupItems)

Here, you run your function to send() on change, but <v-radio-group v-model="selectedColor"> is looking at the selectedColor variable, which you don't change/update.

Vue will automatically update selectedColor when you check the radio group in the UI, but in this case, you need to manually set this.selectedColor inside your watch to update the radio-group itself.

my apologies but the actual code above is but one of the hundreds of thousands (it seems to me) of iterations I have tried.

<<template>
    <v-app>
        <v-container>
            <v-row>
                <v-col cols="12">
                    <h2>Choose your favorite color:</h2>
                    <v-radio-group v-model="selectedColor">
                        <v-radio v-for="radio in radioGroupItems" :label="radio.label"
                            :value="radio.label.toLowerCase()" @click="send(radio)">
                        </v-radio>
                    </v-radio-group>
                    <p>You selected: {{ selectedColor }}</p>
                </v-col>
            </v-row>
        </v-container>
    </v-app>
</template>


<script>
    export default {
  data() {
    return {
      selectedColor:null,
      radioGroupItems :[
        {label:'Red',topic:'Power',payload:'power'},
        {label:'Blue',topic:'Minus',payload:1},
        {label:'Green',topic:'Plus',payload:1}
        ],
    }
  },


    watch: {
      msg: {
        deep: true,
        handler(newVal) {
          if (newVal.payload === 'one') {
             this.selectedColor = "Red";
            this.Power_On();
          }

          if (newVal.payload === 'stop') {
            this.Power_Off()
          }
          
          if (newVal.payload === 'next') {
            this.Power_Next()
          }
        },
      },
    },

    methods: {

      Power_Off: function () {
        this.selectedColor = "Red";
        this.send({ topic: 'Power', payload: 'Off' })
      },

      Power_On: function () {
        this.selectedColor = "Blue";
        this.send({ topic: 'Power', payload: 'On' })
      },

      Power_Next: function () {
        this.selectedColor = "Green";
        this.send({ topic: 'Power', payload: 'Next' })
      },
    },
  }
</script>

here is one of the many that I did use the selected.Color and it did not work either. To me it seems redundant to include that in both the watch and method but I didn't think it would hurt to try. I realize how frustrating it must be to the learned in here to try to explain something so simple to someone but I appreciate the help. If I were to chronicle every different code I tried I am sure the web site would collapse from lack of disk space.

[edit] tried the code bakman2 suggested and it didn't work, sigh..... and I realize that there are some strange commands but this it to try to get me to understand how to make this work and hopefully when I get there I'll modify the code and in the end there will be 7 buttons, this is the mashup of code snippets I've found on the web

It's no problem at all, we're here to help. I'll talk through the principles/architecture to hopefully help you understand.

Principles:

  • You have the watch that checks for any changes in msg, this will occur on incoming msg objects to your ui-template node.
  • In your widget, you have a v-radio-group
    • The v-model here is a data variable defined on your component
    • It will automatically update whenever you make an explicit selection. The :value of each option is what selectedColor will be equated to for the relevant selection.
    • So, if you want to do a programmatic selection, i.e. setting selectedColor in your JavaScript, so that it updates to that selection, the selectedColor you assign in your JavaScript needs to match to one of the :value= attributes in your options.
    • Currently, your :value fields are radio.label.toLowerCase(), but in the JavaScript you're doing this.selectedColor = "Red";, so there is a difference in the case, and therefore the radio-group doesn't reognise Red, Green or Blue as values assigned to an option

Solution:

With your most recent example, either remove the toLowerCase() in the :value attribute, or this.selectedColor = 'red' needs to lower case.

The other piece to note here, is, when clicking the radio option, you emit the full radio object, but in your Power_On functions (and the others) you emit a different msg (with topic/payload)

got to here

<<template>
    <v-app>
        <v-container>
            <v-row>
                <v-col cols="12">
                    <h2>Choose your favorite color:</h2>
                    <v-radio-group v-model="selectedColor">
                        <v-radio v-for="radio in radioGroupItems" :label="radio.label"
                            :value="radio.label" @click="send(radio)">
                        </v-radio>
                    </v-radio-group>
                    <p>You selected: {{ selectedColor }}</p>
                </v-col>
            </v-row>
        </v-container>
    </v-app>
</template>


<script>
    export default {
  data() {
    return {
      selectedColor:null,
      radioGroupItems :[
        {label:'Red',topic:'Power',payload:'power'},
        {label:'Blue',topic:'Minus',payload:1},
        {label:'Green',topic:'Plus',payload:1}
        ],
    }
  },


    watch: {
      msg: {
        deep: true,
        handler(newVal) {
          if (newVal.payload === 'Red') {
             this.selectedColor = "Red";
            this.Power_On();
          }

          if (newVal.payload === 'stop') {
            this.Power_Off()
          }
          
          if (newVal.payload === 'next') {
            this.Power_Next()
          }
        },
      },
    },

    methods: {

      Power_Off: function () {
        this.selectedColor = "Red";
        this.send({ topic: 'Power', payload: 'Off' })
      },

      Power_On: function () {
        this.selectedColor = "Blue";
        this.send({ topic: 'Power', payload: 'On' })
      },

      Power_Next: function () {
        this.selectedColor = "Green";
        this.send({ topic: 'Power', payload: 'Next' })
      },
    },
  }
</script>

and still the button doesn't get selected

Ok, have no idea what I did but went through and cleaned up the code and now it all seems to work. bakman2 asked why all the weird commands so I made them more what I thought I'd need in my actual code, turns out that was a good suggestion.
by the way, thanks for hanging with me to get this done.

2 Likes

Hello,
I am exciting to solve your trouble.
If you share your Desgin , let me try.
I am professional dev.