T dhanunjay
T dhanunjay

Reputation: 820

Issue when trying to use @click="checkedInput" to display checkbox label in Vuejs?

new Vue({
  el: '#app',
  data: {
    checkedNames: [],
    checkedName: true,
    close: false
  },
  methods: {
    uncheck: function(checkedName) {
      this.checkedNames = this.checkedNames.filter(name => name !== checkedName);
    },
    uncheckall: function(event) {
      this.checkedNames = [];
    },
    mouseOver: function() {
      this.close = true;

    },
    mouseOut: function() {
      this.close = false;
    },
    checkedInput(event) {
      if (this.checkedNames.includes(event.target.value)) {
        this.uncheck(event.target.value)
      } else {
        this.checkedNames.push(event.target.value)
      }
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" />
<div id='app'>
  <ul class="checkboxes">
    <li><input type="checkbox" id="jack" value="Jack" @click="checkedInput">
      <label for="jack">Jack</label></li>

    <li><input type="checkbox" id="john" value="John" @click="checkedInput">
      <label for="john">John</label></li>

    <li><input type="checkbox" id="mike" value="Mike" @click="checkedInput">
      <label for="mike">Mike</label></li>
  </ul>
  <br/>
  <ul class="tags">
    <li @mouseover="mouseOver" @mouseleave="mouseOut" @click="uncheck(checkedName)" class="badge badge-pill badge-primary" v-for="checkedName in checkedNames">
      {{ checkedName }}<span v-show="close" aria-hidden="true">&times;</span>
    </li>
    <li class="badge badge-pill badge-danger" @mouseover="mouseOver" @mouseleave="mouseOut" @click="uncheckall" v-show="checkedNames != ''">Clear</li>
  </ul>
</div>
But without using v-model, i want to perfom using @click. issues with above code is (in method i guess checkedInput).

But there is small bug in the above code that is, After clicking the checkbox it is displaying the selected checkbox label but,

When i clear using label, checkbox is not unchecking. 2.)After selecting all checkboxes and if i click on clear, checkboxes not unchecking and if i try to uncheck checkboxes manually then after unchecking label is printing the value and second checkbox label not printing.

Upvotes: 2

Views: 56

Answers (1)

Majed Badawi
Majed Badawi

Reputation: 28414

Using v-model makes it straight-forward. Here is a solution with some refactoring:

new Vue({
  el: '#app',
  data: () => ({ checkedNames: [], close: false }),
  methods: {
    uncheck(checkedName) { this.checkedNames = this.checkedNames.filter(name => name !== checkedName); },
    uncheckall() { this.checkedNames = []; },
    mouseOver() { this.close = true; },
    mouseOut() { this.close = false; }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" />
<div id="app">
  <ul class="checkboxes">
    <li>
      <input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
      <label for="jack">Jack</label>
    </li>
    <li>
      <input type="checkbox" id="john" value="John" v-model="checkedNames">
      <label for="john">John</label>
   </li>
    <li>
      <input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
      <label for="mike">Mike</label>
    </li>
  </ul>
  <br/>
  <ul class="tags">
    <li 
      v-for="(checkedName, checkedNameId) in checkedNames"
      :key="checkedNameId"
      @mouseover="mouseOver" 
      @mouseleave="mouseOut" 
      @click="uncheck(checkedName)" 
      class="badge badge-pill badge-primary" 
    >
      {{ checkedName }}<span v-show="close" aria-hidden="true">&times;</span>
    </li>
    <li 
      class="badge badge-pill badge-danger" 
      @mouseover="mouseOver" 
      @mouseleave="mouseOut" 
      @click="uncheckall" 
      v-show="checkedNames.length"
    >
      Clear
    </li>
  </ul>
</div>

EDIT:

Since you don't want to use the above solution, the issue with your approach is that the array checkedNames is not two-way bound with the inputs hence the changes are not reflected on the template. Therefore, what you can do is fill it from the start and use v-for to render the checkboxes with the ability to modify the checked attribute of each. To render the labels below, you can create a computed property that lists the checked items:

new Vue({
  el: '#app',
  data: () => ({ checkedNames: [ { id:1, name:"Jack", checked:false }, { id:2, name:"John", checked:false }, { id:3, name:"Mike", checked:false } ], close: false }),
  computed: {
    checkedLabels() { return this.checkedNames.filter(({ checked }) => checked === true); }
  },
  methods: {
    uncheckall() { this.checkedNames.forEach(item => item.checked=false); },
    mouseOver() { this.close = true; },
    mouseOut() { this.close = false; },
    checkedInput(checkId) {
      const item = this.checkedNames.find(({ id }) => id === checkId);
      item.checked = !item.checked;
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" />
<div id='app'>
  <ul class="checkboxes">
    <li
      v-for="({ id, name, checked }) in checkedNames"
      :key="id"
    >
      <input 
        type="checkbox" 
        :id="name" 
        :value="name" 
        :checked="checked" 
        @click="checkedInput(id)"
      >
      <label :for="name">{{name}}</label>
    </li>
  </ul>
  <br/>
  <ul class="tags">
    <li 
      v-for="({ id, name}) in checkedLabels"
      :key="id"
      @mouseover="mouseOver" 
      @mouseleave="mouseOut" 
      @click="checkedInput(id)" 
      class="badge badge-pill badge-primary" 
    >
      {{ name }}<span v-show="close" aria-hidden="true">&times;</span>
    </li>
    <li 
      class="badge badge-pill badge-danger" 
      @mouseover="mouseOver" 
      @mouseleave="mouseOut" 
      @click="uncheckall" 
      v-show="checkedLabels.length"
    >Clear</li>
  </ul>
</div>

Upvotes: 2

Related Questions