Search code examples
vue.jsvuejs2vue-componentvuex

Vue computed setter not working with checkboxes?


I have a computed setter:

rating: {
    get() {
        return this.$store.state.rating;
    },

    set(value) {
        console.log(value);

        this.$store.commit('updateFilter', {
            name: this.name,
            value
        });
    }
}

This is linked to my rating like so:

<label>
    <input type="checkbox" :value="Number(value)" v-model="rating">
    {{ index }}
</label>

I expect the computed setter to log an array because when I use a watcher to watch for changes on the rating model I am getting an array.

Except whenever I use a computed setter like above it simply outputs true when a checkbox is selected or false when they are all deselected.

What is going on here, should I just be getting an array just as like with a watcher?


Solution

  • v-model has somewhat "magical" behavior, particularly when applied to checkboxes. When bound to an array, the checkbox will add or remove the value to/from the array based on its checked state.

    It is not clear in your example what value is in Number(value). It should be a value that you want included in the array when the box is checked.

    Taking the example from the Vue docs linked above, I have modified it to use a computed, and it works as you might expect, with the set getting the new value of the array.

    new Vue({
      el: '#app',
      data: {
        checkedNames: []
      },
      computed: {
        proxyCheckedNames: {
          get() {
            return this.checkedNames;
          },
          set(newValue) {
            this.checkedNames = newValue;
          }
        }
      }
    });
    <script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
    <div id="app">
      <input type="checkbox" id="jack" value="Jack" v-model="proxyCheckedNames">
      <label for="jack">Jack</label>
      <input type="checkbox" id="john" value="John" v-model="proxyCheckedNames">
      <label for="john">John</label>
      <input type="checkbox" id="mike" value="Mike" v-model="proxyCheckedNames">
      <label for="mike">Mike</label>
      <br>
      <span>Checked names: {{ checkedNames }}</span>
    </div>