$emit an event from child to parent in vue.js, es6 syntax

You need to $emit on the view model you want to receive your $emit, use a bus or use https://vuex.vuejs.org/.

Emitting to parent directly

The easiest way, is to simply $emit from the child directly to the parent component:

this.$parent.$emit('ChangeView', e.target.dataset.section);

This is OK, but if you have a long chain of components you need to $emit to each $parent in the chain.

Emiting via an Event Bus

You can use Vue to create a global event bus very simply. You create an instance of Vue in your main component, then all other components in your application can emit events to it, and use on to react to those events.

var bus = new Vue({});
var vm = new Vue({
  methods: {
    changeView() {
      bus.$emit('ChangeView', e.target.dataset.section);
    }
  });

It is also possible to emit to $root but this isn't recommended. However, if your app does get quite complex you may want to consider using Vues own state management system, vuex, instead.

Listening for events

You can listen for the $emit in the viewmodel using $on and listening for the specific event:

    var vm = new Vue({
      created() {
         this.$on('ChangeView', section => {
            console.log(section);
          });
      }
    );

This would also be similar is you were using the bus, but you would just reference the bus instead:

bus.$on('ChangeView', ...);

And you may also use it directly in your html using v-on:

<div v-on:ChangeView="doSomething"></div>

If you end up here looking for Vue 3 script setup

It's good practice for readibility to declare emits with defineEmits and then use the returned function for emitting

Child component :

<template>
  <div>
    <button @click="handleClick">Increment</button>
  </div>
</template>

<script setup>
const emit = defineEmits(['custom'])

const handleClick = () => {
  emit('custom')
}
</script>

Parent component :

<template>
  <h1>{{ counter }}</h1>
  <Button @custom="handleCustom"/>
</template>

<script setup>
import { ref } from 'vue'
import Button from './components/Button.vue'

const counter = ref(0)

const handleCustom = () => {
  counter.value++
}
</script>

Here is the working implementation


Unless I'm missing something (very likely), in a simple example like this, you just need to listen for the emitted event in your component. For example, in your parent element, you would have:

<HorizontalNavigation v-on:ChangeView={this.ChangeView} />

Then in your child (HorizontalNavigation) component, you would emit the 'ChangeView' event:

this.$emit('ChangeView', e.target.dataset.section);

I tried this in similar code myself, based on a comment you made on @craig_h's answer, and it was what I needed. I didn't need to emit to parent, or use a bus, or vuex.


In Vue, you can communicate from children up to parent components by emitting events. The child compoment "emits" an event with $emit & the parent component "listens" for it like so:

Child Component:

<template>
  <div>
    <button @click="this.handleClick">Click me!</button>
  </div>
</template>

<script>
export default {
  name: "BaseButton",
  methods: {
    handleClick: function() {
      this.$emit("clickFromChildComponent");
    }
  }
};
</script>

<style scoped>

</style>

Parent Component:

<template>
  <div class="home">
    <h1>Passing a event from child up to parent!</h1>
    <BaseButton @clickFromChildComponent="handleClickInParent"/>
  </div>
</template>

<script>
import BaseButton from "./BaseButton";

export default {
  components: {
    BaseButton
  },
  name: "Home",
  methods: {
    handleClickInParent: function() {
      alert('Event accessed from parent!');
    }
  }
};
</script>

<style scoped>

</style>

You can find a working sample code implementation here & use it in your own context.