Understanding Child to parent custom event emissions

Hello. I’m trying to understand how custom events are emitted to a parent component.

If I understood the docs, this code should make parent component answer the call from its child:

HTML:

<div id="app">
  <father @calling="answer">
    <child>
    </child>
  </father>
</div>

JS:

const myApp = Vue.createApp({});

myApp.component('father',{
	data() {
  	return {
    	valor1: "I am the father"
    }
  },
  template: `<div>{{valor1}}
  					<slot></slot>
  					</div>`,
  methods: {
  	answer() {
    	this.valor1+=" and I hear the call from my son";
    	console.log('I hear the call from my son!!');
    }
  }
});

myApp.component('child',{
	data() {
  	return {
    	valorH: 'I am the child'
    }
  },
  template: `<div>
  			{{valorH}}
        <button @click="call">Call the father</button>
        </div>`,
  methods: {
  	call: function() {
    		console.log("Llamando al padre...");
        this.valorH += " and I am calling my father";
        this.$emit('calling');
    }
  }
});

const vm=myApp.mount('#app');

You can see it in action on this fiddle:
https://jsfiddle.net/macl/ogx7sjuw/52/

I’d like to fire the “calling” event from a method in the child. It should be fired up to the father, who should answer and change its own text. Instead, the child calls its function, but no action happens in the father. Seems like the event is not being received.

Could someone enlighten me about why this doesn’t work and how to make it run properly? Do I have a total misconception about how events work in Vue? Thanks in advance.

Hi there :slight_smile:

The <child></child> tags should be within the ‘father’ component.
Note also that we add the @calling="answer" event listener onto the child component that emitted the event.

I changed the code a little bit in JS Fiddle to explain it to you in code:
JSFiddle

Take a look and let me know if you need any clarity

Hello and thanks for your answer. I see it works as expected if you put the child component into the template. The emitted event is heard by the parent and the callback is executed.

The problem seems to come when the child component is rendered into the slot, which is exactly what I’m trying to do. I’d like to have a container component which renders several different children depending on the value of an specific parent property. Something like this:

<father>
  <child v-if="step==1"></child>
  <child v-if="step==2"></child>
  <child v-if="step==3"></child>
  ...
</father>

Every children would emit a custom event when finished, which should change the property of the parent, making it render the next one until finished (think of it as some kind of slideshow). So, the parent component is some kind of container, abstract to its contents, which would just listen to an event and advance the counter. That’s why I need to have children declared not in the template, but in the HTML page content. I guess I could compose the parent template in the same way you did in your example, but that would break the purpose of having an otherwise generic container component.

Is it possible to achieve what I’m trying to do with slots? Maybe I should “refresh” somehow the events chain of the father when using a slot for rendering the children content? Or is it mandatory to have children declared into the parent template?

I hope I described the issue clear enough. Thanks again.

Hi there. You’re most welcome.
Okay, I think I understand what you’re trying to do.
Unfortunately, I am new to Vue and don’t know what slots are as yet.
Someone here will help you out I’m sure.