Learner
Learner

Reputation: 81

How to make checkbox selected with v-model value for vue-multiselect

Question: on created selected option checkbox is not getting selected, i want checkbox to be selected irrespective checked true/false

Note: value model i always want without checked state into it

below image shows my problem(please see yellow area)

enter image description here

here is what i have tried:

new Vue({
    components: {
    Multiselect: window.VueMultiselect.default
    },
    data: {
    value: [],
    options: [
        {   language: 'JavaScript', library: 'Vue.js', checked: false },
      { language: 'JavaScript', library: 'Vue-Multiselect', checked: false },
      { language: 'JavaScript', library: 'Vuelidate', checked: false }
    ]
    },
  methods: {
    customLabel (option) {
      return `${option.library} - ${option.language}`
    },
    onSelect (option) {
        console.log("Added");
      let index = this.options.findIndex(item => item.library==option.library);
      this.options[index].checked = true;
      console.log(option.library + "  Clicked!! " + option.checked);
    },
    
    onRemove (option) {
        console.log("Removed");
      let index = this.options.findIndex(item => item.library==option.library);
      this.options[index].checked = false;
      console.log(option.library + "  Removed!! " + option.checked);
    }
  },
  created(){
       this.value = [{  language: 'JavaScript', library: 'Vue.js',checked:true }];
  }
}).$mount('#app')
* {
  font-family: 'Lato', 'Avenir', sans-serif;
}

.checkbox-label {
  display: block;
}

.test {
  position: absolute;
  right: 1vw;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link href="https://unpkg.com/[email protected]/dist/vue-multiselect.min.css" rel="stylesheet"/>
<script src="https://unpkg.com/[email protected]/dist/vue-multiselect.min.js"></script>
<div id="app">
  <multiselect 
    select-Label=""
    selected-Label=""
    deselect-Label=""
    v-model="value" 
    :options="options"
    :multiple="true"
    track-by="library"
    :custom-label="customLabel"
    :close-on-select="false"
    @select=onSelect($event)
    @remove=onRemove($event)
    >
    <span class="checkbox-label" slot="option" slot-scope="scope" @click.self="select(scope.option)">
    {{ scope.option.library }}
      <input class="test" type="checkbox" v-model="scope.option.checked" @focus.prevent/>
      
    </span>
  </multiselect>
  <pre>{{ value }}</pre>
</div>

please help me thanks in advance!!

Upvotes: 3

Views: 3744

Answers (3)

tuhin47
tuhin47

Reputation: 6058

You don't need to assign the value as it loses its reactivity there. You just have to select the right option and make it checked. As the below code I've changed the created block

new Vue({
  components: {
    Multiselect: window.VueMultiselect.default
  },
  data: {
    value: [],
    options: [{
        language: 'JavaScript',
        library: 'Vue.js',
        checked: false
      },
      {
        language: 'JavaScript',
        library: 'Vue-Multiselect',
        checked: false
      },
      {
        language: 'JavaScript',
        library: 'Vuelidate',
        checked: false
      }
    ]
  },
  methods: {
    customLabel(option) {
      return `${option.library} - ${option.language}`
    },
    onSelect(option) {
      console.log("Added");
      let index = this.options.findIndex(item => item.library == option.library);
      this.options[index].checked = true;
      console.log(option.library + "  Clicked!! " + option.checked);
    },

    onRemove(option) {
      console.log("Removed");
      let index = this.options.findIndex(item => item.library == option.library);
      this.options[index].checked = false;
      console.log(option.library + "  Removed!! " + option.checked);
    }
  },
  created() {
    // this.value = this.options[0];
    //this.value.checked = true;

    this.value.push(this.options[0]);
    this.value.push(this.options[1]);

    for (let i = 0; i < this.value.length; i++) {
      this.value[i].checked = true;
    }

  }
}).$mount('#app')
* {
  font-family: 'Lato', 'Avenir', sans-serif;
}

.checkbox-label {
  display: block;
}

.test {
  position: absolute;
  right: 1vw;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link href="https://unpkg.com/[email protected]/dist/vue-multiselect.min.css" rel="stylesheet" />
<script src="https://unpkg.com/[email protected]/dist/vue-multiselect.min.js"></script>
<div id="app">
  <multiselect select-Label="" selected-Label="" deselect-Label="" v-model="value" :options="options" :multiple="true" track-by="library" :custom-label="customLabel" :close-on-select="false" @select=onSelect($event) @remove=onRemove($event)>
    <span class="checkbox-label" slot="option" slot-scope="scope" @click.self="select(scope.option)">
    {{ scope.option.library }}
      <input class="test" type="checkbox" v-model="scope.option.checked" @focus.prevent/>
      
    </span>
  </multiselect>
  <pre>{{ value }}</pre>
</div>

Upvotes: 1

Michal Lev&#253;
Michal Lev&#253;

Reputation: 37763

It's a bit hard to understand what you actually want but assuming:

  1. You want to render checkboxes
  2. You don't want checked field in the v-model (so it was added only to help render the checkboxes)

You don't need checked property at all as the value can be easily replaced by simple check against the v-model. That way you can remove a lot of unnecessary code.

See my example below:

new Vue({
  components: {
    Multiselect: window.VueMultiselect.default
  },
  data: {
    value: [],
    options: [{
        language: 'JavaScript',
        library: 'Vue.js'
      },
      {
        language: 'JavaScript',
        library: 'Vue-Multiselect'
      },
      {
        language: 'JavaScript',
        library: 'Vuelidate'
      }
    ]
  },
  methods: {
    customLabel(option) {
      return `${option.library} - ${option.language}`
    },
    isSelected(option) {
      /* unfortunatelly following line does not work as VueMultiselect for some (strange) reason 
        fills the v-model array with copies instead of original objects contained in options
      */
      // return this.value.includes(option)
      return this.value.some((op) => op.library === option.library)
    }
  },
  created() {
    this.value.push(this.options[0])
  }
}).$mount('#app')
* {
  font-family: 'Lato', 'Avenir', sans-serif;
}

.checkbox-label {
  display: block;
}

.test {
  position: absolute;
  right: 1vw;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link href="https://unpkg.com/[email protected]/dist/vue-multiselect.min.css" rel="stylesheet" />
<script src="https://unpkg.com/[email protected]/dist/vue-multiselect.min.js"></script>
<div id="app">
  <multiselect select-Label="" selected-Label="" deselect-Label="" v-model="value" :options="options" :multiple="true" track-by="library" :custom-label="customLabel" :close-on-select="false">
    <span class="checkbox-label" slot="option" slot-scope="scope">
    {{ scope.option.library }}
      <input class="test" type="checkbox" :checked="isSelected(scope.option)" @focus.prevent :key="scope.option.library" />
    </span>
  </multiselect>
  <pre>{{ value }}</pre>
</div>

Upvotes: 2

Abregre
Abregre

Reputation: 480

The package is not working as checkboxes, but more as an array of options, that you can select or not. So if you want to have the options preselected, you have to add them on your v-model array ("value" in this case).

Also the options.checked data is cargo cult here. They are not used for anything.

Example based on your code. your data() should be

options: [
        {   language: 'JavaScript', library: 'Vue.js'},
      { language: 'JavaScript', library: 'Vue-Multiselect'},
      { language: 'JavaScript', library: 'Vuelidate' }
    ],
value: [
        {   language: 'JavaScript', library: 'Vue.js'},
      { language: 'JavaScript', library: 'Vue-Multiselect'},
      { language: 'JavaScript', library: 'Vuelidate' }
    ]

If you start the app using these two in your data, all the options will be preselected.

Upvotes: 0

Related Questions