LX DevBlog

About

Multiple usage of v-model on custom components

10/11/2022
Vue

With Vue3 we can use multiple definitions of v-model.

In the example 2 v-model definitions are implemented on a custom component.

in the Parent:

<template>
  <label>Message</label>
  <CustomInput
    v-model:input="message"
    v-model:valid="isMessageValid"
    :validator="validate"
  />
</template>

<script>
import CustomInput from './CustomInput.vue';

export default {
  components: {
    CustomInput
  },
  data() {
    return {
      message: '',
      isMessageValid: false
    };
  },
  methods: {
    validate(input) {
      return !!input;
    }
  }
};
</script>

in custom component:

<template>
  <input
    type="text"
    v-model="inputValue"
    @input="setValidity"
  />
  {{ validValue }}
</template>

<script>
import { computed } from 'vue';

export default {
  props: {
    input: {
      type: String
    },
    valid: {
      type: Boolean
    },
    validator: {
      type: Function,
      required: true
    },
  },
  setup(props, { emit }) {
    const inputValue = computed({
      get: () => props["input"],
      set: (value) => emit("update:input", value)
    });
    const validValue = computed({
      get: () => props["valid"],
      set: (value) => emit("update:valid", value)
    });
    return {
      inputValue,
      validValue,
    };
  },
  methods: {
    setValidity() {
      this.validValue = this.validator(this.input);
    }
  }
};
</script>

In Vue2 only 1 v-model definition is allowed:

<template>
  <label>Please select one</label>
  <div>
    <div
      v-for="(option, index) in options"
      :key="index"
      @click="selectOption(option)"
    >
      {{ option }}
    </div>
  </div>
</template>

<script>
export default {
  props: {
    value: {
      type: String,
      required: true
    }
  },
  data() {
    return {
      options: ["Choice 1", "Choice 2", "Choice 3"]
    };
  },
  methods: {
    selectOption(option) {
      this.$emit("update:modelValue", option);
    }
  }
};
</script>

  1. value prop is required to use v-model.
  2. The event update:modelValue has to be emitted to change the the value (naming is important).