23

I want to add a v-model on a component but I got this warning:

[Vue warn]: Component emitted event "input" but it is neither declared in the emits option nor as an "onInput" prop.

Here is my code:

// Parent.vue
<template>
  <h2>V-Model Parent</h2>
  <Child v-model="name" label="Name" />
  <p>{{ name }}</p>
</template>

<script setup>
import { ref } from 'vue'
import Child from './Child.vue'

const name = ref('')
</script>
// Child.vue
<template>
  <input
    class="input"
    type="text"
    :placeholder="props.label"
    :value="props.value"
    v-on:input="updateValue($event.target.value)"
  />
</template>

<script setup>
import { defineProps, defineEmit } from 'vue'
const props = defineProps({
  label: String,
  value: String
})
const emit = defineEmit('input')

function updateValue(value) {
  emit('input', value)
}
</script>

I was trying to reproduce this tutorial but I'am stuck and got no idea what I am missing.

I want to display {{ name }} in the Parent.vue component. Do you got an idea how to solve this?

Wenfang Du
  • 8,804
  • 9
  • 59
  • 90
wittgenstein
  • 3,670
  • 7
  • 24
  • 41

3 Answers3

33

In vue 3 value prop has been changed to modelValue and the emitted event input to update:modelValue:

Parent.vue

<Child v-model="name" label="Name" />

Child.vue

<template>
  <input
    class="input"
    type="text"
    :placeholder="props.label"
    :value="props.modelValue"
    v-on:input="updateValue($event.target.value)"
  />
</template>

<script setup>

const props = defineProps({
  modelValue: String
})

const emit = defineEmits(['update:modelValue'])

function updateValue(value) {
  emit('update:modelValue', value)
}
</script>
Kalnode
  • 9,386
  • 3
  • 34
  • 62
Boussadjra Brahim
  • 82,684
  • 19
  • 144
  • 164
  • 1
    This gives typing issues when used with TS, any workaround? – Charles Okwuagwu Jul 07 '21 at 10:22
  • which typing issues? – Boussadjra Brahim Jul 07 '21 at 11:02
  • 2
    `@input="$emit('update:modelValue', $event)"` This should be: `@input="(e)=> $emit('update:modelValue', e.target.value)"` , but TS complains of the latter – Charles Okwuagwu Jul 07 '21 at 11:53
  • did you facing this error? https://stackoverflow.com/questions/71101819/uncaught-typeerror-emit-is-not-a-function-in-vue3 @Boussadjra Brahim – spark Feb 13 '22 at 15:08
  • 1
    import statement is not needed - https://vuejs.org/api/sfc-script-setup.html#defineprops-defineemits for typescript to go errorless read this - https://thisdevbrain.com/how-to-use-v-model-in-vue-3/ – GintsGints May 01 '22 at 06:04
  • @GintsGints I removed the import statement, thanks – Boussadjra Brahim May 01 '22 at 12:11
  • hey @BoussadjraBrahim Unless I am doing something wrong, this doesn't seem to work with multiple checkboxes and the v-model on the parent is always a single value of whatever the last checked checkbox was. Do you know what might be missing? – ToddPadwick Dec 05 '22 at 11:27
14

I like to use with computed as well

<template>
  <div>
    <input v-model="model">
  </div>
</template>

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

const props = defineProps({
  modelValue: {
    type: [String, Number],
    default: ''
  }
})

const emit = defineEmits(['update:modelValue'])

const model = computed({
  get () {
    return props.modelValue
  },

  set (value) {
    return emit('update:modelValue', value)
  }
})
</script>
Douglas Calora
  • 171
  • 1
  • 4
0

I have the similar issues and finally I got it work. Here are one solution for one or multiple checkbox for Vue 3 and TypeScript.

solution : for one or multiple checkbox

CheckBox Component:

        <template>
          <input
            type="checkbox"
            :value="inputValue"
            :disabled="isDisabled"
            v-model="model"
            :class="[defaultClass, inputClass, checkboxClass]"
          />
        </template>
        
    <script lang="ts">
        import { defineComponent, PropType } from 'vue';
        
        export default defineComponent({
          components: {},
        
          props: {
            inputValue: {
              type: String,
              required: false,
              default: '',
            },
        
            modelValue: {
              type: [Object, Boolean] as PropType<String[] | Boolean>,
              required: false,
              default: (() => ({})) || false,
            },
        
            isDisabled: {
              type: Boolean,
              required: false,
              default: false,
            },
        
            checkboxClass: {
              type: String,
              required: false,
              default: '',
            },
          },
        
          data() {
            return {
              defaultClass: 'h-4 w-4 rounded text-primary shadow-sm',
            };
          },
        
          emits: ['update:modelValue'],
        
          computed: {
            model: {
              get() {
                return this.modelValue;
              },
              set(value) {
                this.$emit('update:modelValue', value);
              },
            },
        
            inputClass() {
              if (this.isDisabled) {
                return 'bg-dark-17 border-dark-13';
              }
              return 'bg-dark-23 border-dark-10 hover:bg-dark-25 focus:border-primary';
            },
          },
        });
        </script>

import CheckBox and use it

import CheckBox in other components;

    <div>
      <div v-for="(option, index) in options" :key="index">
        <div
          class="flex items-center justify-between p-6 py-4 border-b border-b-dark-13"
        >
          <div class="w-10">
            <Checkbox :inputValue="option.name" v-model="selectedOptions" />
          </div>
        </div>
      </div>
    </div>
    
      data() {
        return {
          selectedOptions: [],
        };
      },
  • 1
    This solution is not in the vue 3 script setup as requested by the question. Do you have an example of this with setup? as the chosen answer doesn't work for me. – ToddPadwick Dec 05 '22 at 11:29
  • @ToddPadwick, Its working for me with script setup typescript – ReaganM Mar 24 '23 at 21:44