1

I'm new to Vue.js (using Nuxt.js) and what I'm trying to achieve is to have a Select component that I can reuse everywhere and is W3C compliant.

With the help of @Jasmonate answers, I managed to create this component, it's working. But the value attribute is still visible in the source code and so isn't W3C compliant. Maybe the problem is coming from somewhere else in the project ?!

Parent component

<custom-select
  :options="options"
  v-model="selectedOption"
></custom-select>
<span>Selected : {{ selectedOption }}</span>

<script>
  data() {
    return {
      selectedOption: "A",
      options: [
        { label: "One", value: "A" },
        { label: "Two", value: "B" },
        { label: "Three", value: "C" }
      ],
    };
  }
</script>

custom-select.vue

<template>
  <select :value="value" @input="clicked">
    <option
      v-for="option in options"
      :key="option.label"
      :value="option.value"
    >
      {{ option.label }}
    </option>
  </select>
</template>

<script>
  export default {
    props: {
      value: {
        required: true
      },
      options: {
        type: Array,
        required: true
      }
    },
    methods: {
      clicked($event) {
        this.$emit("input", $event.target.value);
      }
    }
  };
</script>

I read those documentation pages:

And also looked around the web to find example of v-model in a custom component, but it's always about the input tag. The only example I found about a custom select with v-model isn't actually a select tag, like the Vue Select plugin or this thread on StackOverflow.

2
  • What's your question? Are you trying to create a custom form component that uses a <select> internally? If so, can you show what you've tried? Commented Oct 23, 2019 at 5:58
  • Hi, thanks for your quick answer and sorry for my not native English, I might have not explain myself well. I am trying to create a custom Select component only. I'm going to edit my first message to add one of the many code I tried. Commented Oct 23, 2019 at 6:03

1 Answer 1

1

v-model is syntax sugar. By default, the value is a prop that has the name value, and it changes (two-way-binding) whenever the event input is emitted.

Also, v-model is bound on the select element, not option.

Your code can be modified as such:

<template>
  <select :value="value" @input="clicked">
    <option
      v-for="option in options"
      :key="option.label"
      :value="option.value"
    >
      {{ option.label }}
    </option>
  </select>
</template>

<script>
  export default {
    props: {
      value: {
        required: true
      },
      options: {
        type: Array,
        required: true
      }
    },
    methods: {
      clicked($event) {
        this.$emit('input', $event.target.value);
      }
    }
  };
</script>

Documentation here: https://v2.vuejs.org/v2/guide/components.html#Using-v-model-on-Components

You can also change the prop name and event name that v-model uses, see: https://v2.vuejs.org/v2/guide/components-custom-events.html#Customizing-Component-v-model

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

7 Comments

Hi @Jasmonate and thanks for your answer. I edited the code in my first message but it still doesn't work. I probably don't understand the links between option.value in option, value in props and $event :s Does $event shoot the option.value or am I suppose to do something more in the method? In the Vue.js example they wrote $event.target.value If I do the html-select tag directly in the parent component, the selectedOption is updated correctly.
Hi, sorry for the confusion, I haven't been using native select in a while. I've fixed my answer.
No worries @Jasmonate, thanks for taking the time to help me! So I modified my code with your corrections and yes it works. But if I want to have a W3C valid code it doesn't accept value on select tag. Error: Attribute value not allowed on element select at this point. <select value="A" data-v-e3eecde6><option>... So I wonder if there is another way to do it?
Vue uses virtual dom, and should strip component properties from HTML element attributes if they are declared as props. I've tried to reproduce this in my local environment ([email protected]) and the value attribute was stripped from <select>. Make sure you have added value to the props object in your component.
If you want to strip all additional attributes, you can try this: vuejs.org/v2/api/#inheritAttrs example: export default { inheritAttrs: false, data() { ... } }
|

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.