[Vuejs]-Custom vue.js checkbox binding an array raises "Avoid mutating a prop directly…" How should I implement this?

0👍

I solved this by creating the local reference to the value prop and a watch on the prop.

Thanks to Midas Dev for pointing me in the right direction. His solution doesn’t provide the two-way binding.

Here’s updated code:

<script type="text/x-template" id="searchable-checkbox">
    <div>
        <input type="text" class="form-control" v-model="text_filter">
        <div style="max-height:200px; overflow-y: auto;">
            <ul class="list-unstyled">
                <li v-for="opt in filtered_options">
                    <label>
                        <input type="checkbox" v-bind:value="opt" v-model="local_value" v-on:change="onChanged($event)">
                        {{opt}}
                    </label>
                </li>
            </ul>
        </div>
    </div>
</script>

Vue.component('searchable-checkbox', {
    template: '#searchable-checkbox',
    data: function() {
        return {
            text_filter: '',
            local_value: this.value
        }
    },
    props: ['options', 'value'],
    methods: {
        onChanged: function($event) {
            this.$emit('input', this.value);
        }
    },
    watch: { 
        value: function(new_value) {
            this.local_value = new_value;
      }
    },
    computed: {
        filtered_options: function() {
            var that = this;
            var lower_text_filter = that.text_filter.toLowerCase();
            return this.options.filter(function(opt) {
                return lower_text_filter.length == 0 || opt.toLowerCase().indexOf(lower_text_filter) >= 0;
            });
        }
    }
})

0👍

<script type="text/x-template" id="searchable-checkbox">
    <div>
        <input type="text" class="form-control" v-model="text_filter">
        <div style="max-height:200px; overflow-y: auto;">
            <ul class="list-unstyled">
                <li v-for="opt in filtered_options">
                    <label>
                        <input type="checkbox" v-bind:value="opt" v-model="checkbox_value" v-on:change="onChanged($event)">
                        {{opt}}
                    </label>
                </li>
            </ul>
        </div>
    </div>
</script>

Vue.component('searchable-checkbox', {
    template: '#searchable-checkbox',
    data: function() {
        return {
            text_filter: '',
            checkbox_value: this.value
        }
    },
    props: ['options', 'value'],
    methods: {
        onChanged: function($event) {
            this.$emit('input', this.checkbox_value);
        }
    },
    computed: {
        filtered_options: function() {
            var that = this;
            var lower_text_filter = that.text_filter.toLowerCase();
            return this.options.filter(function(opt) {
                return lower_text_filter.length == 0 || opt.toLowerCase().indexOf(lower_text_filter) >= 0;
            });
        }
    }
})

Please try it.

Leave a comment