2

I'm trying to set value to select with multiple=true within vue.js. When I'm setting v-model, everything is ok

<select v-model="selected" multiple style="width: 50px;">

but when I'm setting v-bind:value no value is selected in select tag

<select v-bind:value="selected" multiple style="width: 50px;">

Example Code

How can I set read-only value to select?

Update: I'm using this in component, so v-model can't be used, I have to use v-bind:value + v-on:change pair. Change function already done and works like a charm, so no question regarding it.

2
  • what's wrong with v-model? what's your intention to use value? Commented Nov 28, 2018 at 7:55
  • I need value to be read-only, not two-way. Commented Nov 28, 2018 at 7:56

3 Answers 3

2

I'm not sure, but it may be an option:

new Vue({
  el: '#example-6',
  data: {
    selected: ['A', 'B'],
    options: ['A', 'B', 'C']
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="example-6" class="demo">
  <select multiple style="width: 50px;">
     <option v-for="option in options" :selected="selected.indexOf (option) != -1">{{option}}</option>
  </select>
  <br>
  <span>Selected: {{ selected }}</span>
</div>

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

Comments

1

I had the same problem. I searched for some hours to find a solution to forward the value and event.

I started my research in reading source code and I find some interesting things. When you use v-model, vue.js generates a piece of code at runtime. These code retreat the event to simplify the assignement.

This save my life for the case when the select is not multiple, but the problem stayed. I suppose there is something similar for the binding of attribute value, but I didn't find it. If someone have it, I'm interested to have the source.

Finally I found a simple solution. The aim is just forwarding the v-model interactions of select (bind value and input event). I create a component with:

  • computed property model with a getter and setter.
  • a prop value.

With these, we take advantages of the generated piece of code with the setter, because the value passed is the refined value. The getter don't need to be more complex.

{
  props: ["value"],
  computed: {
    model: {
      get: () => {
        // value is a prop of the component
        return this.value;
      },

      set: (valueSelect) => {
        this.$emit("input", valueSelect);
      }
    }
  }
}

The template :

<template>
  <select v-model="model">
    <slot></slot>
  </select>
</template>

I hope this help.

Sorry for the syntax, but I'm writing component in Typescript so it is really different. I write here in typescript and sfc syntax.

<script lang="ts">
import Vue from "vue";
import Component from "vue-class-component";
import { Prop, Watch } from "vue-property-decorator";

@Component
export default class SelectComponent extends Vue {
  @Prop({
    required: true
  })
  private value: any[] | any;

  @Prop({
    default: false
  })
  private multiple: boolean;

  private get model() {
    return this.value;
  }

  private set model(value) {
    this.$emit("input", value);
  }
}
</script>
<template>
  <select v-model="model" :multiple="multiple">
    <slot></slot>
  </select>
</template>

Comments

0

I think you wanted to do:

<div id="example-6" class="demo">
  <select multiple disabled v-model="selected" style="width: 50px;">
    <option>A</option>
    <option>B</option>
    <option>C</option>
  </select>
  <br>
  <span>Selected: {{ selected }}</span>
</div>

Your updated jsfiddle.

v-model actually uses v-bind behind the scenes. If you only use v-bind you'll be missing the input event handling and no change to the input will be propagated to the state.

Update:

Using v-bind:value, it's only possible to select one option:

v-bind:value="selected[0]" // in the select tag

And you may also do like:

<div id="example-6" class="demo">
  <select multiple disabled style="width: 50px;">
    <option :selected="selected[0]">A</option>
    <option :selected="selected[1]">B</option>
    <option :selected="selected[2]">C</option>
  </select>
  <br>
  <span>Selected: {{ selected }}</span>
</div>

jsfiddle

Here's a more elegant way for this:

<div id="example-6" class="demo">
  <select multiple disabled style="width: 50px;">
    <option v-for="(option, index) in options" :selected="selected[index]">
    {{ option }}
  </option>
  </select>
  <br>
  <span>Selected: {{ selected }}</span>
</div>

jsfiddle

3 Comments

exactly, but via value, not via options.
I'm using this in component, so v-model can't be used, I have to use v-bind:value + v-on:change pair. v-on:change is already implemented.
the updated answer has all it can be done. hope this helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.