I'm doing a project and I need to call parent methods from child components. How can this be accomplished in Vue.js?
You should use this.$emit('myEvent')
inside of your child component, when you want to trigger the method in the parent.
Then find your child component in the template of the parent and add an event catcher on it like this:
<template>
<your-child-component @myEvent="myMethod"/>
</template>
If you want to add parameters to your method, you can add a second parameter to your emit like this:
this.$emit("myEvent", "My parameter")
For this to work you don't have to change anything in the event "catcher", as long as the method you call has a parameter.
Maybe working example will make it more clear.
https://m-vue-leaflet.netlify.app/
code- https://github.com/manojkmishra/vue-leaflet-mapping
So here if you see there are 3 vue files in components folder. Brew.vue is parent component to BrewList.vue child component.
Brew.vue- Parent Component
BrewList.vue - Child Component
Child component BrewList.vue is using emit to send mouse-over-brew & mouse-leave-brew values to parent Brew.vue. Also, in case you are interested Brew.vue parent is sending brew prop to BrewList.vue child.
As per docs- https://v2.vuejs.org/v2/guide/components.html#Listening-to-Child-Components-Events
It works with $emit
. The name of @callTest in parent component must be same as the name of $emit('callTest') in child component.
Parent Component:
<template>
<Child
@callTest="test" // Assign 'test' method to @callTest
/>
</template>
<script>
import Child from "../components/Child.vue";
import { defineComponent } from "vue";
export default defineComponent({
name: "Parent",
components: {
Child,
},
methods: {
test() {
alert("Test");
},
}
});
</script>
Child Component:
<template>
<button @click="$emit('callTest')">Click Me</button>
</template>
<script>
import { defineComponent } from "vue";
export default defineComponent({
name: "Child",
});
</script>
Again, the name of @callTest in parent component must be same as the name of $emit('callTest') in child component.
If you use $emit
in script
section, this
is needed different from template
section.
Child Component:
<template>
<button @click="message">Click Me</button>
</template>
<script>
import { defineComponent } from "vue";
export default defineComponent({
name: "Child",
methods: {
message() {
this.$emit('callTest') // 'this' is needed.
}
}
});
</script>
If test
method has 2 parameters
, you need to call test
method with 2 arguments
in child component like below.
Parent Component:
<template>
<Child
@callTest="test" // Assign 'test' method to @callTest
/>
</template>
<script>
import Child from "../components/Child.vue";
import { defineComponent } from "vue";
export default defineComponent({
name: "Parent",
omponents: {
Child,
},
methods: {
test(num1, num2) { // 'test' method has 2 parameters.
alert(num1 + num2);
},
}
});
</script>
Child Component:
<template> // Call 'test' method with 2 arguments.
<button @click="$emit('callTest', 3, 5)">Click Me</button>
</template>
<script>
import { defineComponent } from "vue";
export default defineComponent({
name: "Child",
});
</script>
Ideally, this is the right way to do so: https://v2.vuejs.org/v2/guide/components.html#Listening-to-Child-Components-Events
On the other hand, I believe in your scenario (which I'm trying to assume cause it's not really clear), you can use this.$parent.methodName.
Keep in mind that the second suggestion is less clean. It should be used just in case of need.
So basically, there are 2 ways to answer your question
Using $emit, with syntax is @
Passing function as props, with syntax is : The same as your example
If you based on Vue docs and a lot of other Vue tutorials, you will see that they encourage people to use $emit event rather than passing function as props (the way you are using). The docs you can read here.
https://v2.vuejs.org/v2/guide/components-custom-events.html https://v2.vuejs.org/v2/guide/components.html#Emitting-a-Value-With-an-Event https://code.tutsplus.com/tutorials/design-patterns-for-communication-between-vuejs-component--cms-32354 vue, emitting vs passing function as props
The reason is Vue philosophy is passing props down, emitting events up. Using $emit will help to mark the function triggered as a Vue event, and therefore you can use global event listener. This will also may help you to separate between data flow logic and event flow logic.
However, using function as props is not wrong, and in fact, it can be used to achieve the same result. In my preference, I use the 2nd way when I write a component that has a default function, and the function is only overridden when parents pass another one. This will help me avoid rewriting default functions many times.
For the rest of the other cases, I will use the 1st way $emit.
Parent
<complited v-on:passData="fromChild" />
methods: {
fromChild(data) {
if (data.methodCall) return this[data.methodCall]();
}
aFunction() {
alert('function: a');
}
bFunction() {
alert('function: b');
}
}
Child
<template>
<div>
<button @click="parentCall()">Call Parent Function
</button>
</div>
</template>
methods: {
parentCall() {
this.$emit("passData", {methodCall: 'aFunction' });
}
}
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