moses toh
moses toh

Reputation: 13162

How can I call method in child component from parent component?

I have 4 component

My component first like this :

<template>
    ...
     <component-second></component-second>
    ...
</template>
<script>
    ...
    export default {
        ...
        updated() {
            // call check method in the component fourth
        }
    }
</script>

My component second like this :

<template>
    ...
     <component-third></component-third>
    ...
</template>
<script>
    ...
    export default {
        ...
    }
</script>

My component third like this :

<template>
    ...
     <component-fourth></component-fourth>
    ...
</template>
<script>
    ...
    export default {
        ...
    }
</script>

My component fourth like this :

<template>
    ...
</template>
<script>
    ...
    export default {
        ...
        methods: {
            check() {
                ...
            }
        }
    }
</script>

So, if update() in component first executed, I want to call check method in the component fourth

How can I do it?

Upvotes: 1

Views: 3058

Answers (2)

Omar Tanti
Omar Tanti

Reputation: 1448

What I would try is to create a data element in the parent method and pass it along its children, then watch it in the component-four and on change of its value trigger the check method.

<template>
    ...
    <component-second update-flag="updateFlag"></component-second>
    ...
</template>
<script>
...
export default {
    data(){
        return {
            updateFlag: true;
        }
    }
    updated() {
        // call check method in the component fourth
       updateFlag = !updateFlag;
    }
}
</script>

Component-second:

<template>
    ...
    <component-third update-flag="updateFlag"></component-third>
    ...
</template>
<script>
...
export default {
    ...
    props: ['updateFlag']
}
</script>

Component third:

<template>
    ...
    <component-fourth update-flag="updateFlag"></component-third>
    ...
</template>
<script>
...
export default {
    ...
    props: ['updateFlag']
}
</script>

Component fourth:

<template>
    ...
</template>
<script>
...
export default {
    ...
    props: ['updateFlag'],
    watch: {
        updateFlag: function (val) {
            this.check();
        }
    },
    methods: {
        check() {
            ...
        }
    }
}
</script>

Upvotes: 1

acdcjunior
acdcjunior

Reputation: 135742

You can use a Vue instance as event bus.

You would create a global variable:

var eventHub = new Vue(); // use a Vue instance as event hub

To emit events you would use in any component:

eventHub.$emit('myevent', 'some value');

And, to listen to that event, again, in any component, do:

eventHub.$on('myevent', (e) => {
    console.log('myevent received', e)
});

Demo:

var eventHub = new Vue(); // use a Vue instance as event hub

Vue.component('component-first', {
    template: "#component-first-tpl",
    data() { return {someFlag: true} },
    updated() {
      eventHub.$emit('myevent', 'some value');
    }
});
Vue.component('component-second', {
    template: "#component-second-tpl"
});
Vue.component('component-third', {
    template: "#component-third-tpl"
});
Vue.component('component-fourth', {
    template: "#component-fourth-tpl",
    created() {
      eventHub.$on('myevent', (e) => {
      	console.log('myevent received', e)
        this.check();
      });
    },
    methods: {
        check() {
            console.log('check called at fourth');
        }
    }
})

new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue.js!'
  }
})
<script src="https://unpkg.com/vue"></script>

<template id="component-first-tpl">
    <div>
        <component-second></component-second>
        
        <br>
        someFlag: {{ someFlag }}
        <button @click="someFlag = !someFlag">Trigger update</button>
    </div>
</template>
<template id="component-second-tpl">
    <div>
        <component-third></component-third>
    </div>
</template>
<template id="component-third-tpl">
    <div>
        <component-fourth></component-fourth>
    </div>
</template>
<template id="component-fourth-tpl">
    <div><h1>I'm Number 4</h1></div>
</template>

<div id="app">
  <p>{{ message }}</p>
  <component-first></component-first>
</div>

Note: If creating a dedicated instance as event hub is something complicated in your environment, you can replace eventHub with this.$root (inside your components) and use your own Vue instance as hub.

Upvotes: 5

Related Questions