I do have three components.
I don't have any influence on what the Datatable
component does cause I have it from npm.
Now I want to send an event from EditButton
to my Zonelist
.
Zonelist
component:
<template>
<datatable :columns="table_columns" :data="table_rows" filterable paginate v-on:remove="removeItem"></datatable>
</template>
<script>
import datatable from 'vuejs-datatable';
import moment from 'moment';
export default {
data() {
return {
table_columns: [
{label: "Zone", component: 'ZoneLink'},
{label: "Last updated", callback (row) {
let locale = $('html').closest('[lang]').attr('lang') || 'en';
moment.locale(locale);
return moment(row.last_updated).format('D. MMM YYYY');
}},
{label: '', component: 'EditButton'}
],
table_rows: [
{
"name": "xyz.de",
"last_updated": "2017-10-21 17:29:50"
}
],
form: {
name: '',
errors: []
}
};
},
components: {
datatable
},
methods: {
removeItem (item) {
this.table_rows.forEach((value, index, array) => {
if (value.name === item) {
Vue.delete(array, index);
}
});
}
}
}
</script>
Now my EditButton
component $emit()
's the remove
event with a parameter.
But nothing happens. So I think vue is not able to locate the listener.
(I'm using method shorthands from ES6 here)
How could I do this properly without mutating Zonelist
's state via this.$parent.$parent
from the EditButton
?
Vue events don't bubble the component tree on their own. However when writing wrapper components this can be the desired behaviour. This code registers a global bubble directive which allows to re-emit all given events: Let's say we want to bubble events start , accelerate and brake of our component Car .
We add an argument to the v-on directive, which will be the name of the event we want to handle. In the above example case, it is a click event. After that, we have to bind an expression to the directive, which will normally be a method you want to use to handle the event. In this case, we've called it clickHandler.
Non parent-child communication in Vue is typically handled via either an event bus, or a state management system.
In this case, unless your application is more complex, the event bus is probably all you need. Since you are using single file components, you may need to declare the bus on the window, probably in your main script.
window.bus = new Vue()
Then in your EditButton
, you can emit the event
bus.$emit('some-event', someData)
And in your ZoneList
you can listen for it.
bus.$on('some-event', someData => this.doSomething(someData))
Another option is to ask DataTable
to pass any and all events up by adding a v:on="$listeners"
attribute to it.
See https://stackoverflow.com/a/61329264/578318 for a more detailed explanation.
Edit:
A much safer option would be to simply listen to the event in the parent class and pass it on...
<ancestor @message="console.log($event)"> <!-- cute trick see * -->
...
<parent @message="$emit('message', $event)"> <!-- passes it on -->
...
<child @click="$emit('Hello World')"> <!-- creates the event -->
*
computed: {'console' : () => console}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With