3

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/vue-multiselect@2.0.2/dist/vue-multiselect.min.css" rel="stylesheet"/>
<script src="https://unpkg.com/vue-multiselect@2.0.3/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!!

Learner
  • 61
  • 2
  • 21

3 Answers3

1

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/vue-multiselect@2.0.2/dist/vue-multiselect.min.css" rel="stylesheet" />
<script src="https://unpkg.com/vue-multiselect@2.0.3/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>
tuhin47
  • 5,172
  • 4
  • 19
  • 29
  • your above solution works!! but let say onclick of someting i need to pre-populate the selected tags in that case i don't know how it works. as i know created is called only 1 time – Learner Jul 09 '21 at 07:15
  • i tried i like this onclick of a button `if(this.value.length){ for(let i = 0; i < this.value.length; i++){ this.value[i].checked = true; } }` – Learner Jul 09 '21 at 07:30
  • it did not work for me `this.values` had 2 items – Learner Jul 09 '21 at 07:32
  • Actually, Multiselect supports an array as well as an object. You need to use an array always as you can select multiple selections. I modified my answer please check now – tuhin47 Jul 09 '21 at 08:31
1

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/vue-multiselect@2.0.2/dist/vue-multiselect.min.css" rel="stylesheet" />
<script src="https://unpkg.com/vue-multiselect@2.0.3/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>
Michal Levý
  • 33,064
  • 4
  • 68
  • 86
0

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.

Abregre
  • 486
  • 4
  • 11
  • let assume `v-model="value"` having all items as `checked:true` – Learner Jul 07 '21 at 07:14
  • I edited my answer with an example based on your code – Abregre Jul 07 '21 at 07:20
  • the actual problem is `checkbox` is not getting selected, please see my above image – Learner Jul 07 '21 at 07:22
  • but vue-multiselect doesn't work that way. The item is selected by changing background color. If it is selected, on hove it is red etc... If you want to send the value to your backend, you just need to add it in your value array. – Abregre Jul 07 '21 at 07:37
  • in created it is there no `this.value = [{ language: 'JavaScript', library: 'Vue.js' }];` without `checked:true` – Learner Jul 07 '21 at 07:38
  • Every object in your value array, should match at least 1 object from your options array. So if you want to use with checkbox, add the checked value in your value assignment on created(). Can you show me an example of the data that your backend endpoint waits for? – Abregre Jul 07 '21 at 09:01