0

I am using a checkbox.

<template v-for="(item,index) in items">
    <div >
        <input type="checkbox"  
            v-model="item.checked"
            @click="selectionCheckboxClicked(index,item.checked)"   
        />
    </div>          
    .....

And this is the JS code

selectionCheckboxClicked: function selectionCheckboxClicked(index,checked) {
            console.log(this.items[index].checked);
            console.log(checked);
            ....
        },

Initial value of item.checked is false. When I click the checkbox in Chrome or IE, it checks the checkbox and displays 'true' in console log. However, when I run the code in Firefox, though it does change the state, console log displays false in selectionCheckboxClicked(). I need to take some action based on the current state of the checkbox in selectionCheckboxClicked(), which I ma finding difficult to implement in the current situation.

Shall appreciate any suggestions to fix the issue.

user761100
  • 2,171
  • 4
  • 23
  • 31

2 Answers2

1

Because for checkbox, v-model bind @change not @input (check Vue Github: source codes for v-model). Then @change will be fired after lose focus.

But you should not rely on the order either @click or @change will be executed first (check this answer for more details).

So one solution is uses @change=handler($event) instead, because v-model uses addHandler with one parameter named important=true to make sure it will be fired first than your event handler.

new Vue({
  el: '#app',
  data() {
    return {
      testValues: false
    }
  },
  methods: {
    selectionCheckboxClicked: function(ev) {
      console.log(this.testValues);
      console.log(ev.target.checked);
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
  <div>
    <input type="checkbox" v-model="testValues" @change="selectionCheckboxClicked($event)" />
  </div>
</div>

Or another solution is uses @input but you should rely on what is checked or not on the input Dom element.

new Vue({
  el: '#app',
  data() {
    return {
      testValues: false
    }
  },
  methods: {
    selectionCheckboxClicked: function(ev) {
      console.log('v-model:', this.testValues);
      console.log('inputCheckedAtDom:', ev.target.checked);
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
  <div>
    <input type="checkbox" v-model="testValues" @input="selectionCheckboxClicked($event)" />
  </div>
</div>

If you still like to use @click, one solution actually is same as @input. Uses one ref to access the input Dom element.

new Vue({
  el: '#app',
  data() {
    return {
      testValues: false
    }
  },
  methods: {
    selectionCheckboxClicked: function(ev) {
      console.log('v-model:', this.testValues);
      console.log('inputCheckedAtDom:', this.$refs.test.checked);
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
  <div>
    <input ref="test" type="checkbox" v-model="testValues" @click="selectionCheckboxClicked($event)" />
  </div>
</div>

setTimeout will work because it will be executed after current task finished and re-render. Even you uses setTimeout(()=>{}, 0)(delay 0 seconds), it will still work.

Sphinx
  • 10,519
  • 2
  • 27
  • 45
0

What seems to be happening is that Firefox calls the click function immediately even before the v-model = "item.checked" has changes. When I check the value of this.items[index].checked after some delay (say 100 ms), it displays true.

console.log(this.items[index].checked); console.log(checked);

    var self = this;
    setTimeout(function()
        { if (self.items[index].checked)
                self.selectedContactsCount++; 
              else
                  self.selectedContactsCount--; 
             },
            100);
user761100
  • 2,171
  • 4
  • 23
  • 31