How can I use v-model with a functional template component in Vue?

MaYaN

Vue.js has an example demonstrating how to build a functional component wrapping a button:

<template functional>
  <button
    class="btn btn-primary"
    v-bind="data.attrs"
    v-on="listeners"
  >
    <slot/>
  </button>
</template>

But how can I build a similar component working with select which I can then use v-model on its parent?

I have come up with the following, but when I use v-model on it like so:

<MyComponent :Label="'Status'" :Data="Statuses" v-model="selectedStatus" />

The value of selectedStatus becomes:

[object Event]
<template functional>
    <select v-bind:value="data.attrs" v-on="listeners">
        <option>-</option>
        <option v-for="item in props.Data" :key="item" :value="item">{{item}}</option>
    </select>
</template>

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

@Component
export default class TaskSelector extends Vue {
  @Prop({ type: String, required: true })
  public Label!: string;

  @Prop({ type: Array, required: true })
  public Data!: string[];
}
</script>
tony19

For v-model to work properly, the component must receive a value prop and emit an input event whose data is a string value. But the <select>'s native input event data is an InputEvent object, converted to a string ([object Event]), which yields the incorrect result with the bound v-model.

To fix this, we need to modify the <select>'s input event data before it reaches the parent. This requires removing <select v-on="listeners">, which would've allowed the problematic native input event to propagate to the parent. We then use listeners.input($event.target.selectedOptions[0].value) to forward the input event with the selected option's string value.

Steps:

  1. Add a value prop, and bind the <select>'s :value to the value prop
  2. Re-emit the <select>'s input event with the selected option's value. This should replace v-on="listeners".

Your SFC should look like this:

<template functional>
  <select
    1️⃣:value="props.value"
    2️⃣@input="listeners.input && listeners.input($event.target.selectedOptions[0].value)"
  >
    <option value="">-</option>
    <option v-for="item in props.Data" :key="item" :value="item">{{item}}</option>
  </select>
</template>

demo

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

How can I use {...this.props} in a functional component

How can I use forwardRef in functional component in react native?

How can I prevent a method called by a Vue component from running every time the v-model changes?

How to use v-model on component in vue 3 script setup

How can I use a component template in any module or component?

Vue - how can i render a script inside a component template?

How can I put a data inside the <template> in a component with Vue

How Can I Call Template in Same Component on Vue

How can I refresh React Functional component?

How can I access my Vue component's data property using a string as it's property name in a v-model directive?

How can I use a template component with objects in Aframe?

How can I use a Django template variable in HTML in a model TextField?

How can I use single file vue component with symfony 4?

how to use the component from other vue in template

How can I access methods of a component using ref in functional component

How can I check if the component is unmounted in a functional component?

How can I make a component render onClick in a React functional component?

How can I convert class component to functional component?

React: How can I acces to props of a functional component in a class component

How can I use hooks in a higher-order function that returns a ReactNative functional component in TypeScript?

How can i update my react component with the use of hooks in functional way

How can i use the same behavior as react-router's Link on a function within functional component?

How can I use react-typed within a functional component along with refs?

How to use a plugin's directive in a functional component - Vue 2

Can I use hooks inside a function (not a functional component)

Can I define a Vue JSX component within a SFC <script setup> and use it in the SFC template?

Can I variably choose what Vue.js component to use in a template?

Is it possible to use a v-model from inside a component template?

Can I use loops inside a model using functional API?