Emit Events in Vue to pass Data between Components
This practical guide provides code snippets about custom events in Vue which can be used to pass data up the component tree. For regular DOM events like click
please refer to the Vue Docs.
Now, data always flow down the component tree in Vue or other frontend frameworks - with props. But, how to pass data up without using global state like Vuex?
Passing data up to the parent component - with custom events
Using custom events allows us to pass data up the component tree, or notify the parent component that a custom event has happened - if no data is being passed.
But what if we need to notify a parent component that some event has been triggered in a child or even pass data upwards?
The answer is emitting custom events in Vue.
We need to take care of these steps to emit events in Vue:
- Think about the trigger for the event: a condition in a method, computed property or watcher in child component from where the event is emitted
- Emit the event with
this.$emit("my-custom-event", \[data\])
when the condition is met - Catch the event bubbling up to a parent component
Event naming convention: Custom event names should be in kebab-case like in
my-custom-event
. In addition, it is not recommended to use capital letters like in PascalCase or camelCase since HTML event handlers are case-insensitive.
1. Trigger the event with a custom condition
For this step it is essential to define in which case the event should be emitted. We need to define a condition inside a computed property, a method or a watcher in order to get there.
Suppose we're having a form and want to pass the input value up to the parent when the form is being submitted.
Let's dive right into the example code:
// ChildComponent.vue
<template>
<form v-on:submit="onSubmit">
<input v-model="inputValue" type="text" />
<button>Submit</button>
</form>
</template>
<script>
export default {
name: "ChildComponent.vue",
data() {
return {
inputValue: ""
}
},
methods: {
onSubmit() {
this.$emit("form-submitted", this.inputValue);
}
}
}
</script>
In this example ChildComponent we're defining the condiction when the event shall be emitted: When the form is being submitted. Our event handler is a method onSubmit()
.
It is very common to include form validation inside event handlers for submitting forms. A minimal example of form validation in this case is shown next:
// ChildComponent.vue with form validation
methods: {
onSubmit() {
if (!this.inputValue) {
console.error("Please insert some text...");
} else {
this.$emit("form-submitted", this.inputValue);
}
}
}
Event modifiers
In the example above we're making use of the regular submit event and a custom event we called
form-submitted
. It is important to differentiate, here.
click
and submit
are the most common regular DOM events. The v-on
-directive provides several event modifiers in case you want to call event.preventDefault()
or event.stopPropagation()
.
Here are quick examples for event modifiers on click
or submit
events in Vue:
// click events propagation will be stopped
<a v-on:click.stop="handleClick">Click</a>
// The submit event will no longer trigger a page reload
<form v-on:submit.prevent="onSubmit"></form>
If you want to know more about event modifiers check out the Vue Docs.
2. Catch the event in a parent component
Now, inside the parent component we need to catch the emitted event and setup a handler method there.
// ParentComponent.vue
<template>
<child-component v-on:form-submitted="handleFormData" />
</template>
<script>
export default {
name: "ParentComponent",
data() {
return {
formData: []
}
},
methods: {
handleFormData(formDataFromChild) {
this.formData.push(formDataFromChild);
}
}
}
</script>
Inside our handleFormData
method we are simply putting the form data passed from the child component in the local state of the parent component.
You may also see the short-hand version of
v-on
, which is@
because it is so frequently used in Vue.
<child-component v-on:form-submitted="handleFormSubmit" />
// is equal to
<child-component @form-submitted="handleFormSubmit" />