Home > Software engineering >  Is it possible to use a prop as a v-model value?
Is it possible to use a prop as a v-model value?

Time:10-21

Is it possible to use the value of a prop as the input's v-model?

I normally do the following when creating an input:

<template>
    <form>
        <input v-model="form.email" type="email"/>
    </form>
</template>

<script>
export default {
    data() {
        return {
            form: {
                email: '',
            }
        }
    }
}
</script>

But now I'm trying to achieve the following where this.myProp is used within the v-model without being displayed as a string on the input:

<template>
    <form>
        <input v-model="this.myProp" type="email"/>
    </form>
</template>

<script>
export default {
    props: ['myProp'] // myProp = form.email for example (to be handled in a parent component)
}
</script>

CodePudding user response:

Yes, but while using it in parent component. In child component you need to extract value and @input instead of using v-model (v-model is shortcut for value="" and @input) Here is an example of input with label, error and hint in Vue 3 composition API.

BaseInput.vue

<template>
    <div >
        <label>{{ label }}</label>
        <input v-bind="$attrs" :placeholder="label" :value="modelValue" @input="$emit('update:modelValue', $event.target.value)">
        <span v-for="item of errors" >{{ item.value }}</span>
        <span v-if="hint" >{{ hint }}</span>
    </div>
</template>

<script setup>
defineProps({ label: String, modelValue: String | Number, errors: Array, hint: String })
defineEmits(['update:modelValue'])
</script>

Using v-bind="$attrs" you target where attributes like type="email" need to be applied in child component. If you don't do it, it will be added to the top level DOM element. In above scenario <div>.

ParentComponent.vue

<BaseInput type="email" v-model="formData.email" :label="Email" :errors="formErrors.email"/>

CodePudding user response:

You can use computed prop and update v-model:

const app = Vue.createApp({
  data() {
    return {
      form: {
        email: '[email protected]',
      }
    }
  },
})
app.component('child', {
  template: `
    <form>
      <input v-model="model" type="email" />
    </form>
  `,
  props: {
    modelValue: String
  },
  emits: ['update:modelValue'],
  computed: {
    model: {
      get() {
        return this.modelValue
      },
      set(newValue) {
        this.$emit('update:modelValue', newValue)
      }
    }
  }
})
app.mount('#demo')
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
<div id="demo">
  {{ form.email }}
  <child v-model="form.email"></child>
</div>

  • Related