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>

🧠 Test Your Knowledge

What does $emit() do in Vue?