30 Days of Vue

Vue Components - Custom Events


This post is part of the series 30 Days of Vue.

In this series, we're starting from the very basics and walk through everything you need to know to get started with Vue. If you've ever wanted to learn Vue, this is the place to start!

Vue Components - Custom Events

Yesterday, we saw how props can be used to pass data downwards from parent to child. Today, we'll see how custom events can facilitate communication in the opposite direction - from child to parent.

In the last two articles - we introduced components, seen how they help make our Vue applications more modular and taken a look at how props help pass data from parent to child components.

What if we needed to find a way to communicate information in the opposite direction (i.e. have the child component notify the parent about something)?

At the last stage of building our mock twitter app, we had the root instance render a tweet-component which subsequently rendered a tweet-content component of its own. Props were used to pass the relevant tweet data object from the root instance downwards to tweet-component and further down to tweet-content.

Assume we wanted to introduce a new link (or button) to the tweet element.

Upon click of the new link, let's attempt to re-introduce another copy of the same tweet element into the bottom of the list of tweets. Though this might be a strange use case, it'll be a useful way to show how we intend to communicate information from the child up to the parent.

The link that adds a new element upon click will be part of the tweet-content component while the data (tweets array) that controls the tweet elements in our list is part of the root instance.

To add a new tweet to the list of tweets, we'll essentially need to push a new tweet object into the tweets array. When the user clicks the link to add another tweet, we'll need to have some sort of event propagated up to the root instance to change the data kept in the instance. We can’t use props for this since props can only be used to pass data downwards (parent to child to grandchild). Since we want to create communication in the opposite direction, we can use something known as Vue Custom Events.

Custom Events

Custom events in Vue behave very similar to native JavaScript custom events but with one key distinction - Vue custom events are used primarily for communication between components as opposed to communication between DOM nodes.

Vue custom events are triggered using $emit while specifying the name of the custom event:


The $emit function can have a second optional argument that allows the caller to pass arbitrary values along with the emitted event:

this.$emit('name-of-event', {
  data: {
    course: '30 Days of Vue';

The this keyword is a reference to the instance in which the event is being triggered. When declaring an event within the template of a component, the this keyword can be omitted.

In our mock twitter application, let’s update the template of tweet-content to contain the link that represents the ability to re-add the same tweet element to the bottom of the list. We’ll attach a click event listener on the link that when triggered will emit a custom event with the name of add. In the custom event declaration, we’ll also pass the tweet prop object as the event payload.

Vue.component('tweet-content', {
  template: `
    <div class="media-content">
      <div class="content">
        // ...       
      <div class="level-left">
        // ...
        <a class="level-item"
          @click="$emit('add', tweet)">
          <span class="icon is-small">
            <i class="fas fa-plus"></i>
  props: ['tweet']

Upon click of the newly added link, the add event will get propagated one level up to tweet-component. For parent components to be able to listen to events emitted by children, the v-on directive can be used to create a custom event listener. That custom event listener needs to be declared where the child component is being rendered.

Since tweet-component doesn’t have access to the tweets data array that we want to update, we’ll need to propagate the event one level higher. To achieve this, we’ll create a custom event listener in tweet-component to listen for when the add event is triggered in tweet-content. When the event is triggered, we’ll trigger another add event and pass in the event object (i.e. the tweet object payload). This updates the template of tweet-component to the following:

Vue.component('tweet-component', {
  template: `
    <div class="tweet">
      <div class="box">
        <article class="media">
          // ...
          <tweet-content :tweet="tweet"
            @add="$emit('add', $event)">
  props: ['tweet']

In the event listener, we’re able to access the event object that has been passed with $event.

In the root template, we can now create the final listener. We’ll specify the event listener where tweet-component is being rendered and when triggered call a method labelled addTweetMessage. addTweetMessage will pass in the $event payload as the only argument to the method.

      <tweet-component v-for="tweet in tweets"

The entire source code for this tutorial series can be found in the GitHub repo, which includes all the styles and code samples.

If at any point you feel stuck, have further questions, feel free to reach out to us by:

Get started now

Join us on our 30-day journey in Vue. Join thousands of other professional Vue developers and learn one of the most powerful web application development frameworks available today.

No spam ever. Easy to unsubscribe.