Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to emit event from child to parent in Vue3 with <script setup> syntax?

I have the following component:

<SomeModal :is-modal-active="isAddingThing" @close="isAddingThing = false" />

Inside that component looks like this:

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

const props = defineProps({
    isModalActive: Boolean,
})

const handleClose = () => {
    emit('close') // doesn't work
}
</script>

<template>
<V-Modal @close="handleClose">
    ...
</V-Modal>
</template>

How do I emit to parent?

like image 516
agm1984 Avatar asked Jul 05 '21 18:07

agm1984


People also ask

How do I emit an event in Vue?

Emitting Events with setup()$emit() to send our event. Instead, we can access our emit method by using the second argument of our setup function – context . context has access to your components slots, attributes, and most importantly for us, its emit method. We can call context.

How do I pass Click event from parent to child in Vue?

To pass an event from parent to child, we can pass a Vue instance to the child, emit events from the parent, and listen to it with the Vue instance we passed into the child.

What is emit in Vue JS?

Vue $emit is a function that lets us emit, or send, custom events from a child component to its parent. In a standard Vue flow, it is the best way to trigger certain events.

How does Vue emit work with child components?

Many Vue patterns involve passing data from a parent component to its children using props. But what if we need a child to affect its parent? Using emit, we can trigger events and pass data up the component heirarchy. This is useful for things like: How does Vue Emit Work? When we emit an event, we invoke a method with one or more arguments:

Can we emit custom events in VUE 3?

Vue 3 — Custom Events. We can emit events from child to… | by John Au-Yeung | JavaScript in Plain English Vue 3 is in beta and it’s subject to change. Vue 3 is the up and coming version of Vue front end framework. It builds on the popularity and ease of use of Vue 2. In this article, we’ll look at how to emit and handle custom events with Vue 3.

How to pass events from parent component to child component?

When a component wants to let its parent know something has happened, it fires an event outside of itself When the parent wants to let the child know that something has changed, it modifies the prop that is passed to the child component' So you don't pass events to a child-component, you change the prop of a child.

What is an event bus in Vue?

The event bus is a cleaner, more efficient way to achieve independent ocmmunication between components in Vue.js without passing through a parent component. But depending on your use perhaps using Vuex… all depends. make a simple event bus…


Video Answer


2 Answers

With Vue version 3.2, if you want to emit an event from inside <script setup>, then all you have to do is define your emits with the defineEmits() method that is automatically available inside <script setup> (you don't have to import it), then you can emit the event by calling emit('myEventName', myParams). Here's some sample code...

<script setup>
const emit = defineEmits(['eventA', 'eventB'])
function btnClick(params) {
    emit('eventA')
    emit('eventB', params)
}
</script>
like image 57
McGrew Avatar answered Oct 17 '22 16:10

McGrew


Update 2022

The useContext and getCurrentInstance APIs were deprecated and are no longer exposed to the Vue 3 API. Instead of that, you should use the defineEmits at the root level on the setup script.

<template>
  <button @click="action('🎉')"></button>
</template>
<script setup>
  const emit = defineEmits(['close', 'unClose'])
  const action = (id) => emit('close', val);
</script>

and for typescript the definition would be:

const emit = defineEmits<{
  (e: 'close', val: string): void
  (e: 'unClose', id: number): void
}>()

Outdated, Pre-Vue 3.2

  • You don't need to define emit at all to run $emit from the template
  • useContext provides the emit function for use in setup function
  • using defineEmits adds the list of emits to the component (equivalent to emits: definition of component) but doesn't help with the emit

useContext

<template>
  <button @click="action('🎉')"></button>
  <!-- emit is defined through useContext -->
  <button @click="emit('action1','🥑')">1</button>
  <!-- $emit here doesn't need to be defined -->
  <button @click="$emit('action2','🦄')">2</button>
</template>
<script setup>
  import { defineProps, useContext } from 'vue'
  const { emit } = useContext()
  const action = (id) => emit('action', id);
</script>

Note that vetur extension might tell you that it's deprecated and that you should use useSlots and useAttrs instead. If you want to use emit from the script, those, obviously, won't help with that.

getCurrentInstance

import { defineProps, getCurrentInstance} from 'vue'
const { emit } = getCurrentInstance()

In addition to running an emit, vue3 allows (recommends🤷‍♂️) that the emits are defined, so the component parent might know what events a component might emit. To do that using the <script setup> form, you can use defineEmit

<script setup>
  import { defineEmit } from 'vue'
  const emit = defineEmit(['action'])
  const action = (id) => emit('action', id);
</script>

This will allow sending action emit event, but if you emit a doit although it will still emit, you'll get a warning in the console

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

like image 32
Daniel Avatar answered Oct 17 '22 17:10

Daniel