3

I am trying to make a form which contains an input group section, in this group, there are one select box and multiple checkboxes. Checkboxes are populated based on the select box selection. There is also an add and remove button to generate and remove input group. The select box is used with v-model to filtered the checkboxes. But when I generate a new input group and make changes, all checkboxes are changed. I want them to be isolated. How can I achieve?


Here is my Template.

<template>
    <form @submit.prevent="onSubmit">
        <div v-for="(variationProduct, index) in variationProducts" :key="variationProduct.id">
            <div class="from-group mb-4">
                <label class="col-form-label"><b>Categories :</b></label>
                <select class="form-control mr-2" ref="categories" v-model="category">
                    <option value="0">Please select category...</option>
                    <option v-for="category in categories" :key="category.id" :value="category.id">
                        {{ category.name }}
                    </option>
                </select>
                <div v-if="hasError">
                    <validation-errors v-if="errors['categories.'+index]" :errors="errors">
                        {{ errors['categories.'+index][0] }}
                    </validation-errors>
                </div>
            </div>
            <div class="form-group mb-4">
                <label class="col-form-lablel"><b>Variation Products :</b></label>
                <div class="row">
                    <div v-for="filteredVariationProduct in filteredVariationProducts" :key="filteredVariationProduct.id">
                        <div class="col-12">
                            <input :id="filteredVariationProduct.id" :value="filteredVariationProduct.id" type="checkbox" ref="variationProducts">
                            <label :for="filteredVariationProduct.id">{{ filteredVariationProduct.name }}</label>
                        </div>
                    </div>
                </div>
                <div v-if="hasError">
                    <validation-errors v-if="errors['variationProducts.'+index]" :errors="errors">
                        {{ errors['variationProducts.'+index][0] }}
                    </validation-errors>
                </div>
            </div>
            <div class="float-right">
                <button @click.prevent="add" class="btn btn-success">Add</button>
                <button @click.prevent="remove(index)" class="btn btn-danger">Remove</button>
            </div>
            <br>
            <br>
            <hr>
        </div>
        <input type="submit" class="btn btn-primary" value="Submit">
    </form>
</template>


Here is my JS.

<script>
import ValidationErrors from './ValidationErrors.vue';

export default {
    components: { 
        'validation-errors': ValidationErrors,
    },
    data () {
        return {
            variationProducts: [],
            categories: [
                { id: 1, name: 'Technology'},
                { id: 2, name: 'Business'},
                { id: 3, name: 'Marketing'},
                { id: 4, name: 'Development'},
                { id: 5, name: 'Engineering'},
            ],
            category: 0,
            activeVariationProducts: [],
            count: 1, 
            errors: {},
            hasError: false,
        }
    },
    methods: {
        add: function() {
           this.count++;
           this.errors = {};
           this.hasError = false;
           this.variationProducts.push({ id: this.count });
        },
        remove: function (index) {
            if ( this.variationProducts.length > 0 && index > -1) {
                this.variationProducts.splice(index, 1);
            } else {
                alert('Must have at least one input!')
            }
        },
        onSubmit: function() {
            console.log(this.$refs.variationProducts.value);
        },
        generateVariationProducts: function(num) {
            for(let i = 1; i <= num; i++) {
                let activeVariationProduct = {
                    id: i,
                    name: 'Product '+ i,
                    category_id: i
                };
                this.activeVariationProducts.push(activeVariationProduct);
            }
        },
    },
    computed : {
        filteredVariationProducts: function () {
            let categoryId = parseInt(this.category);
            if (categoryId !== 0) {
                let filteredVariationProducts = this.activeVariationProducts.filter((variationProduct) => {
                    return variationProduct.category_id === categoryId;
                });
                return filteredVariationProducts;
            } else {
                let filteredVariationProducts = this.activeVariationProducts;
                return filteredVariationProducts;
            }
        }
    },
    created () {
        this.variationProducts.push({ id: this.count });
        this.generateVariationProducts(10);
    },
}
</script>

2
  • is there any specific reason why you have nested both - categories and filteredVariationProducts within variationProducts iteration? Can you post sample of variationProducts member object? Commented Jan 29, 2019 at 6:31
  • variationProducts is just an empty array of object. I nested them in order to get the respective category with variation products. Then user can check the variation products and then all will be submitted with $refs in form. Commented Jan 29, 2019 at 7:26

1 Answer 1

5

Here is a sample code. This code Shows how you can use multiple Checkboxes that is generated dynamically and how to make them isolated -

new Vue({
  el : "#app",
  data : {
    Items : ["One", "Two", "Three"],
    newCheckbox : "",
    SelectedItems : {
      'One' : "",
      'Two' : "",
      'Three' : "",
    },
  },
  methods:{
    add:function(){
      Vue.set(this.SelectedItems, this.newCheckbox, false);
      this.Items.push(this.newCheckbox);
    },
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.22/vue.min.js" type="text/javascript"></script>
<div id="app">
  
  <div>
    <label v-for="(item, index) in Items">
      <input type="checkbox" v-bind:key="index" v-model="SelectedItems[item]"> {{ item }} 
    </label>
  </div>
  <div>
    <input type="text" v-model="newCheckbox">
    <button @click="add">Add</button>
  </div>
  <div>
    Output : {{ SelectedItems }}
  </div>
</div>

You can dynamically add new checkbox and still they are isolated

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.