eslint-plugin-vue icon indicating copy to clipboard operation
eslint-plugin-vue copied to clipboard

vue/require-explicit-emits - defineModel not supported

Open Pentadome opened this issue 1 year ago • 4 comments

What did you do?

<script setup lang="ts">
defineModel<string>();
</script>

<template>
  <input @input="$emit('update:modelValue', $event.target.value)" />
</template>

This causes warning/error: The "update:modelValue" event has been triggered but not declared on defineEmits.

Pentadome avatar Sep 04 '24 10:09 Pentadome

Is this the recommended usage? I'd rather do this with defineModel:

<script setup lang="ts">
const modelValue = defineModel<string>();
</script>

<template>
  <input @input="modelValue = $event.target.value" />

  <!-- or even better: -->
  <input v-model="modelValue" />
</template>

FloEdelmann avatar Sep 04 '24 11:09 FloEdelmann

What about rest of cases, where you use it with $emit ? its still doesnt work as IMHo suppose to work, meaning if you use defineModel you expect to have interface api modelValue and emit update:modelValue defined, so eslint should not scream about it. Its there, explained in vue docs, its just eslint-plugin-vue does not support it

Szymon-dziewonski avatar Jun 13 '25 15:06 Szymon-dziewonski

This is still relevant for me. As a use case, reusable components leveraging UI libraries tend to define their own models while passing them to the UI component as well. Example with a ConfirmDialog :

<script setup lang="ts">
defineModel<boolean>('visible')

const emit = defineEmits<{
  'submit': [name: string]
}>()

const name = ref('')
function handleSubmit() {
  emit('submit', name.value)
}
</script>

<template>
  <!-- Dialog is a UI component from PrimeVue -->
  <Dialog
    :visible="visible"
    @update:visible="$emit('update:visible', $event)">
    <form @submit="handleSubmit">
      <input v-model="name" type="text" />

      <div>
        <Button
          label="Cancel"
          @click="$emit('update:visible', false)" />
        <Button
          label="Create"
          type="submit" />
      </div>
    </form>
  </Dialog>
</template>

corentind59 avatar Nov 09 '25 10:11 corentind59

@corentind59 See my comment above; you could rewrite this as follows:

<script setup lang="ts">
const visible = defineModel<boolean>('visible')

const emit = defineEmits<{
  'submit': [name: string]
}>()

const name = ref('')
function handleSubmit() {
  emit('submit', name.value)
}
</script>

<template>
  <!-- Dialog is a UI component from PrimeVue -->
  <Dialog
    :visible="visible"
    @update:visible="visible = $event">
    <form @submit="handleSubmit">
      <input v-model="name" type="text" />

      <div>
        <Button
          label="Cancel"
          @click="visible = false" />
        <Button
          label="Create"
          type="submit" />
      </div>
    </form>
  </Dialog>
</template>

FloEdelmann avatar Nov 10 '25 08:11 FloEdelmann