[Vuejs]-$emit event is not being heard in Vue components

0๐Ÿ‘

I suggest controlling the state from the parent to have more control instead of your child component relying on your maybe-not-available parent.

Example:

Parent

<template>
  <div>
    <button @click.prevent="saveTradeClick" class="btn btn-primary">Save</button>
    <child :traded="traded"></child>
  <div>
</template>
<script>
export default {
  data: () => ({ traded: false }),
  methods: {
    saveTradeClick() {
      this.traded = true;
    },
  },
};
</script>

Child

<template>
  <div><div>
</template>
<script>
export default {
  props: ['traded'],
  watch:{
    traded(val) {
      if (val) this.submitTrade();
    },
  },
};
</script>

Vue unwritten rules

  • Parents are allowed to reference children, e.g. via props or refs
  • Children do not have any reference to the parent
  • Children do not change data that is passed via props.

0๐Ÿ‘

Another idea for If you would like a child component to listen for events from the parent is to create an Event Bus.

Now this feature does not come out of the box ready to use so you have to actually create a new instance of Vue and then export the EventBus feature like so.

eventbus.js

import Vue from 'vue';
export const EventBus = new Vue();

You would then import the EventBus into the components you would like to interact with.

parent component

<template>
  <div class="pleeease-click-me" @click="emitGlobalClickEvent()"></div>
</template>

<script>
// Import the EventBus we just created.
import { EventBus } from './event-bus.js';

export default {
  name: 'Parent',
  data() {
    return {
      clickCount: 0
    }
  },

  methods: {
    emitGlobalClickEvent() {
      this.clickCount++;
      // Send the event on a channel (i-got-clicked) with a payload (the click count.)
      EventBus.$emit('i-got-clicked', this.clickCount);
    }
  }
}
</script>

So in your child component you can now listen for the event i-got-clicked

child component

<script>
// Import the EventBus we just created.
import { EventBus } from './event-bus.js';

export default {
  name: 'Child',

  mounted() {
    EventBus.$on('i-got-clicked', clickCount => {
     console.log(`Oh, that's nice. It's gotten ${clickCount} clicks! :)`)
  });
}
</script>

and clickCount was passed from the parent so you can share data a long with listening for events.

And another solution depending on the size of your application is to look in to vuex

Leave a comment