1

How can input of type checkbox present in child component be bonded to v-model on the parent component?

Required Component Way -

Parent-

<button v-if="checkedNames">Confirm</button> //show this button if 1 checkbox is selected
<div v-model="checkedNames" >
<child-component  v-for="person in collection" :key="person.id"  
:person="person"><child-component>
</div>

new Vue({
  el: '...',
  data: {
    checkedNames: [],
    collection: [
      {id: 1, name: 'Jack', items:[{id:100,name:"Pen",quantity:5}]},
      {id: 2, name: 'John', items:[{id:200,name:"Pen",quantity:10},
        {id:201,name:"Paper",quantity:100,}]},
      {id: 3, name: 'Mike', items:[{id:300,name:"Pen",quantity:20}]},
    ]
  }
})

Child-

<div v-for="(item, i) in person.items" :key="i">
<input type="checkbox" :id="item.id" :value="item.name" >
<label :for="item.id">{{item.name}}</label>
<input type="number" :id="i" :value="item.quantity" >
<label :for="i">{{item.quantity}}</label>
</div>

new Vue({
  el: '...',
  props:{person:Object}
})

How to send the item id, quantity and main id if the checkbox is selected to the parent?

3 Answers 3

2
  1. Using v-model on Components
  2. new Vue() is to use only to create top-level Vue instance (usually called vm or app). Components used as a child elements must be registered instead - Component Registration
  3. Always use :key with v-for - Maintaining State

Vue.component('checkboxes', {
  props: ['value', 'options'],
  template: `
  <div>
    <template v-for="item in optionsWithKey">
      <input type="checkbox" :id="item.key" :value="item.name" v-model="model" :key="item.key">
      <label :for="item.key">{{item.name}}</label>
    </template>
  </div>
  `,
  computed: {
    model: {
      get() { return this.value },
      set(newValue) { this.$emit('input', newValue) }
    },
    optionsWithKey() {
      return this.options.map(item => ({
        ...item,
        key: "checkbox_"+ item.id
      }))
    }
  }
})

new Vue({
  el: '#app',
  data: {
    checkedNames: [],
    options:[
      {id: 1, name: 'Jack'},
      {id: 2, name: 'John'},
      {id: 3, name: 'Mike'},
    ]
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.14/vue.js"></script>
<div id='app'>
  <checkboxes v-model="checkedNames" :options="options">
  </checkboxes>
  <pre>{{ checkedNames }}</pre>
</div>

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

Comments

0

I'm not sure but try it...

child:

<input type="checkbox" :id="item.id" :value="item.name" :change="$emit('valueChecked',item.name)">

And in parent:

<child-component @valuChecked="getValue"><child-component>

methods:{
getValue(value){
 this.checkedNames.push(value);
}

}

Comments

-1

See if this helps

// parent template

  <child-component @update:checked-names="updateCheckedNames">
  <child-component>

// parent

  data() {
    return {
      checkedNames: []
    };
  },
  methods: {
    updateCheckedNames(name) {
      if (this.checkedNames.includes(name)) {
        const index = this.checkedNames.indexOf(name);
        this.checkedNames.splice(index, 1);
      } else {
        this.checkedNames.push(name);
      }
    }
  }

// child template

  <div v-for="item in collection">
    <input type="checkbox"
      :id="item.id"
      :value="item.name"
      @click="$emit('update:checked-names', item.name)"> // emit here
    <label :for="item.id">
      {{item.name}}</label>
  </div>



1 Comment

Click event is not the only way a checkbox can be changed – tab and enter keys can be used, or the browser can even remember the previous state. I believe the change event is safer to use

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.