Reputation: 2658
I've been banging my head against this problem for hours. I can't see a problem and from what I can tell I am following the documentation here: https://v2.vuejs.org/v2/guide/components-custom-events.html
code below
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="wrap">
<test-listen>
<test-emit></test-emit>
</test-listen>
</div>
<script>
Vue.component('test-listen', {
data: function(){
return {};
},
methods: {
customHandler : function(e){
console.log(e);
console.log("works");
}
},
template: `
<div class='test_listen' v-on:custom="customHandler">
<slot></slot>
</div>
`
});
Vue.component('test-emit',{
data: function(){
return {};
},
methods: {
clickHandler : function(){
this.$emit('custom');
}
},
template : `
<div class='test_emit' v-on:click="clickHandler">
test
</div>
`
});
new Vue({
el:"#wrap"
});
</script>
<style>
.test_listen{
display:block;
padding:20px;
border:1px solid #000;
}
.test_emit{
display:block;
width:100px;
height:100px;
background-color:#f0f;
color:#fff;
font-weight:700;
font-size:20px;
}
</style>
But the listeners are definitely bound to the element, because if I dispatch a vanillaJS CustomEvent it triggers the console log just fine. What am I missing?
Upvotes: 9
Views: 62625
Reputation: 553
I see only one mistake here. You should add v-on
to the child component.
When you $emit('custom')
from inside it will call "customHandler" on the parent component.
<test-listen>
<test-emit v-on:custom="customHandler"></test-emit>
</test-listen>
Upvotes: 13
Reputation: 9693
There are 2 things wrong here.
If you really want to pass data here and there without restriction better to use Global Event Bus Approach
Working example of your code with some minor correction.
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="wrap">
<test-listen>
</test-listen>
</div>
<script>
Vue.component('test-listen', {
data: function(){
return {};
},
methods: {
customHandler : function(e){
console.log(e);
console.log("works");
}
},
template: `
<div class='test_listen' >
<test-emit v-on:custom="customHandler"></test-emit>
</div>
`
});
Vue.component('test-emit',{
data: function(){
return {};
},
methods: {
clickHandler : function(e){
// e => event : didnt pass here as console will stuck so
this.$emit('custom', 'somedata');
}
},
template : `
<div class='test_emit' v-on:click="clickHandler">
test
</div>
`
});
new Vue({
el:"#wrap"
});
</script>
<style>
.test_listen{
display:block;
padding:20px;
border:1px solid #000;
}
.test_emit{
display:block;
width:100px;
height:100px;
background-color:#f0f;
color:#fff;
font-weight:700;
font-size:20px;
}
</style>
Upvotes: 3
Reputation: 27729
With this.$emit()
is a way to say to the parent component that hey i created an event and now you can listen on this event
You are doing well but you don't listen in parent component the event emitted by child. I made it to work.Click here to see it in action
So in order to make your code to work,In test-listen component,use as child the test-emit component.
Then inside the div #wrap
use the test-listen component
Your problem was that you did't listen to the event in parent component.
Upvotes: 2