Reputation: 566
I have a simple Event bus that changes styles on a page and it works. The event bus is called with the name of the event bus and $emit
and $on
:
EventBus.$on
and
EventBus.$emit('call-modal', { type: 'success' });
How can I make so that instead of calling it with $on
and $emit
I can call it with this.$root.$emit
so that I can use it in every other component? I tried but currently it doesn't work, why?
Here is my App.vue:
<template >
<div id="app">
<bankAccount>
</bankAccount>
<div :class="['modal', `modal--type--${modalType}`]" v-show="showModal">
<slot name="title">e</slot>
<slot name="description"></slot>
</div>
</div>
</template>
<script>
import bankAccount from './components/bankAccount.vue'
import Vue from 'vue'
export const EventBus = new Vue()
export default {
name: 'app',
components: {
bankAccount,
},
data() {
return {
showModal: false,
modalType: 'default',
}
},
created() {
EventBus.$on('call-modal', obj => {
this.showModal = true
this.modalType = obj.type
})
},
}
</script>
<style>
.modal {
height: 100px;
width: 300px;
border: solid gray 2px;
}
.modal--type--success {
border-color: green;
}
.modal--type--danger {
border-color: red;
width: 100%;
}
.modal--type--warning {
border-color: yellow;
width: 100%;
}
</style>
And my component:
<template>
<div>
<button class="pleeease-click-me" @click="callModal()">Click me</button>
</div>
</template>
<script>
import { EventBus } from '../App.vue';
export default {
name: 'bankAccount',
data() {
return {
showModal: false
}
},
methods: {
callModal() {
this.showModal = !this.showModal
EventBus.$emit('call-modal', { type: 'success' });
}
}
}
</script>
<style scoped>
.modal {
height: 100px;
width: 300px;
}
</style>
Upvotes: 0
Views: 2333
Reputation: 4779
To achieve desired result you have to slightly change your code.
In your App.vue
change these lines of code:
created() {
this.$root.$on('call-modal', obj => {
this.showModal = true
this.modalType = obj.type
})
},
And then in your component:
callModal() {
this.showModal = !this.showModal
this.$root.$emit('call-modal', { type: 'success' })
}
Notice that approach suggested by @Dadboz, is preferable, than you desirable.
Upvotes: 1
Reputation: 3108
Simply add that to the instance prototype :
// main.js
//import vue from 'vue'
Vue.prototype.$eventHub = new Vue();
// new Vue({
// ...
// })
now you can use it on any component with :
this.$eventHub.$emit('call-modal');
Upvotes: 1
Reputation: 15616
You can create a separate eventbus.js
file and include it to all of your components. This way, they'll be using the same eventbus instance. TL;DR: it's been explained here:
https://alligator.io/vuejs/global-event-bus/
Long one:
Create an eventbus.js
file with this content:
import Vue from 'vue';
export const EventBus = new Vue();
Then include it:
import { EventBus } from './event-bus.js';
Then use it:
EventBus.$on("event", function(data){
// do stuff with data
});
with
EventBus.$emit("event", data);
and don't forget to remove the event on destruction:
beforeDestroy {
EventBus.$off("event");
}
Upvotes: 1