Vue $emit()
Sending data from child to parent components
📤 What is $emit()?
The $emit() method allows child components to send messages and data to parent components. It enables upward communication, letting children notify parents about events like button clicks, form submissions, or data changes happening inside them.
<!-- ChildButton.vue -->
<template>
<button @click="sendMessage">
Click Me
</button>
</template>
<script setup>
const emit = defineEmits(['buttonClicked'])
function sendMessage() {
emit('buttonClicked', 'Hello from child!')
}
</script>
<!-- Parent.vue -->
<template>
<ChildButton @buttonClicked="handleClick" />
<p>{{ message }}</p>
</template>
<script setup>
import { ref } from 'vue'
const message = ref('')
function handleClick(msg) {
message.value = msg
}
</script>
Output:
Hello from child!
$emit() Features
Upward Flow
Send data from child to parent
emit('eventName', data)
Custom Events
Create your own event names
defineEmits(['myEvent'])
Pass Data
Send values with events
emit('update', value)
Event Handling
Parent listens with @
<Child @myEvent="handler" />
🔹 Basic $emit() Example
Simple event without data:
<!-- AlertButton.vue -->
<template>
<button @click="emit('showAlert')">
Show Alert
</button>
</template>
<script setup>
const emit = defineEmits(['showAlert'])
</script>
<!-- Parent.vue -->
<template>
<AlertButton @showAlert="showMessage" />
</template>
<script setup>
function showMessage() {
alert('Button was clicked!')
}
</script>
Output:
Click the button to trigger alert
🔹 Emitting with Data
Send data along with the event:
<!-- InputField.vue -->
<template>
<input
v-model="text"
@input="emit('textChanged', text)"
placeholder="Type something..."
>
</template>
<script setup>
import { ref } from 'vue'
const emit = defineEmits(['textChanged'])
const text = ref('')
</script>
<!-- Parent.vue -->
<template>
<InputField @textChanged="updateText" />
<p>You typed: {{ userText }}</p>
</template>
<script setup>
import { ref } from 'vue'
const userText = ref('')
function updateText(value) {
userText.value = value
}
</script>
Output:
You typed:
🔹 Counter with $emit()
Child updates parent's counter:
<!-- CounterButtons.vue -->
<template>
<div>
<button @click="emit('increment')">+1</button>
<button @click="emit('decrement')">-1</button>
<button @click="emit('reset')">Reset</button>
</div>
</template>
<script setup>
const emit = defineEmits(['increment', 'decrement', 'reset'])
</script>
<!-- Parent.vue -->
<template>
<div>
<h3>Count: {{ count }}</h3>
<CounterButtons
@increment="count++"
@decrement="count--"
@reset="count = 0"
/>
</div>
</template>
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
Output:
Count: 0
🔹 Form Submission with $emit()
Send form data to parent:
<!-- UserForm.vue -->
<template>
<form @submit.prevent="submitForm">
<input v-model="name" placeholder="Name">
<input v-model="email" placeholder="Email">
<button type="submit">Submit</button>
</form>
</template>
<script setup>
import { ref } from 'vue'
const emit = defineEmits(['formSubmitted'])
const name = ref('')
const email = ref('')
function submitForm() {
emit('formSubmitted', {
name: name.value,
email: email.value
})
name.value = ''
email.value = ''
}
</script>
<!-- Parent.vue -->
<template>
<UserForm @formSubmitted="handleSubmit" />
<p v-if="userData">
Submitted: {{ userData.name }} - {{ userData.email }}
</p>
</template>
<script setup>
import { ref } from 'vue'
const userData = ref(null)
function handleSubmit(data) {
userData.value = data
}
</script>
Output:
Fill and submit to see data
🔹 Multiple Parameters
Emit multiple values at once:
<script setup>
const emit = defineEmits(['updateUser'])
function sendUpdate() {
emit('updateUser', 'John', 25, 'Developer')
}
</script>
<!-- Parent receives -->
<template>
<Child @updateUser="handleUpdate" />
</template>
<script setup>
function handleUpdate(name, age, role) {
console.log(name, age, role)
// Output: John 25 Developer
}
</script>