I have a reusable Badge component. I want to be able to add a close/delete button when an onDelete event listener is present on the component instance.
<template>
<div class="flex inline-flex items-center px-2.5 py-0.5 text-xs font-medium select-none" :class="[square ? '' : 'rounded-full']">
<slot />
<button class="cursor-pointer ml-2" @click="$emit('onDelete')">
<XIcon class="flex-shrink-0 h-3.5 w-3.5 text-gray-400 hover:text-gray-500" aria-hidden="true" />
</button>
</div>
</template>
<script>
import { XIcon } from '@heroicons/vue/solid';
export default {
props: {
color: { type: String },
square: { type: Boolean, default: false },
},
components: {
XIcon,
},
emits: ['onDelete'],
};
</script>
If I add a v-if statement to the button, the emit event is executed immediately
<button v-if="$emit('onDelete')" class="cursor-pointer ml-2" @click="$emit('onDelete')">
I'm using Vue 3
UPDATE: If your component is using the new emits option in Vue3, which is the recommended best practice from the Vue3 docs, the event listeners will not be apart of the $attrs
. An issue will be submitted to the Vue team for clarification and guidance on why this behaves this way.
I have simplified your example above in StackBlitz to isolate the functionality you are after.
Important note, I am using Vue 3.2.26.
In Vue3 $listeners were removed.
Event listeners are now part of $attrs
. However simply console logging this.$attrs
in Badge
won't display the key you are looking for, they are within targets
but accessible by prepending on
to the bound event name. In your case in the Badge
component you will use onOnDelete
.
Complete working example with Two Badges. One will display because it has a bound event onDelete
, the other will not due to the fact that the bound onDelete
is not present.
https://stackblitz.com/edit/vue-8b6exq?devtoolsheight=33&file=src/components/Badge.vue