81

I am using Vue.Js v2. I want to call component1->c1method in component2->c2method for reload data after submitting.

Vue.component('component1', {
  methods: {
    c1method: function(){
     alert('this is c1method')
    },
  }
})
Vue.component('component2', {
  methods: {
    c2method: function(){
     component('component1').c1method()//like this
    },
  }
})
1

9 Answers 9

72

For non-parent-child relation, then this is the same as this one. Call one method, apparently any method of a component from any other component. Just add a $on function to the $root instance and call form any other component accessing the $root and calling $emit function.

On First component

    ....
    mounted() {
        this.$root.$on('component1', () => {
            // your code goes here
            this.c1method()
        }
    }

and in the second component call the $emit function in $root

    ...
    c2method: function(){
     this.$root.$emit('component1') //like this
    },

It acts more like a socket. Reference here

https://stackoverflow.com/a/50343039/6090215

Sign up to request clarification or add additional context in comments.

4 Comments

Basically what happens is you can add events to the vue instance using $on function and naming the event and what function it triggers, and you can trigger that event using $emit function and calling event name. what I did was create an event bus on the root instance of Vue using $root and now I can trigger that event from any child instance. More on this here => vuejs.org/v2/api/#Instance-Methods-Events
The first code segment is missing a ")" at the second to last bracket
@MirAymanAli does it only work in the mounted()?
@YongPin what we are potentially doing is adding the function to the vue global event bus. mounted is the safest bet. but if you want to attach it dynamically do it with caution as the other component won't know when the event is attached. this solution works only if the two components are on the same view port, meaning you are viewing both the component at the same time.
58
// Component A
Vue.component('A', {
    created() {
        this.$root.$refs.A = this;
    },
    methods: {
        foo: function() {
            alert('this is A.foo');
        }
    }
});

// Component B
Vue.component('B', {
    methods: {
        bar: function() {
            this.$root.$refs.A.foo();
        }
    }
});

4 Comments

This makes my screen go blank. I'm using Vue3.
is this.$root safe if i am accessing a method in App.vue ?
I prefer my components to be independent. I feel using an event pattern is prettier since that makes the dependency opt-in.
FEI, in Vue.js 3.2.13 this produces an Exception with a message saying that the $root object can't be extended.
26

No need for hacky solutions.
In vuejs we can create events that can be listened globally.
With this feature, whenever we want to call our beloved function, we just emit this event.
Now, we just listen to this event all the time from the component. whenever this global event happens we can execute our method we want to call.

It's pretty simple:

  1. you go to main.js, before creating the vue instance, write this:
export const eventBus = new Vue(); // added line


new Vue({
    ...
    ...
    ...
    render: h => h(App)
}).$mount('#app');


  1. Anywhere we want to fire the target function, we dont fire it, we just emit this event:
eventBus.$emit('fireMethod');
  1. Now in our component that has the target function, we always listen to this event:
created() {
    eventBus.$on('fireMethod', () => {
            this.myBelovedMethod();
    })
}

Dont forget to import eventBus in top.

import {eventBus} from "path/to/main.js";

thats it, few lines of code, no hacky, all vuejs power.

Comments

19

The docs address this situation

https://v2.vuejs.org/v2/guide/components.html#Non-Parent-Child-Communication

If your components have the same parent, you can emit an event that the parent listens to. Then with the ref property set, you can call the c1method from the parent.

https://v2.vuejs.org/v2/guide/components.html#Child-Component-Refs

Comments

14

Try this out.

<template>
 ...
 <component1 ref='componentOne'>
...
</template>
<script>
  Vue.component('component2', {
    methods: {
     c2method: function(){
       this.$refs.componentOne.c1method();
     }
   }
  });
</script>

Comments

5

If anyone is looking for a solution in Vue.js v3:

https://v3-migration.vuejs.org/breaking-changes/events-api.html#event-bus

https://github.com/developit/mitt#install

    import mitt from 'mitt'
    
    const emitter = mitt()
    
    // listen to an event
    emitter.on('foo', e => console.log('foo', e) )
    
    // listen to all events
    emitter.on('*', (type, e) => console.log(type, e) )
    
    // fire an event
    emitter.emit('foo', { a: 'b' })
    
    // clearing all events
    emitter.all.clear()

Comments

3

I found a good solution for Vue 3 in this SO question and answer https://stackoverflow.com/a/72348802/18091372

It uses Vue3's defineExpose function to make an internal function available outside of the component.

If you have a structure like this in ComponentA

<template>
    <div>
       <ComponentB ref="componentb" />
    </div>
</template>

where ComponentB has:

<script setup>
defineExpose( {internal_function} )

function internal_function() {
    console.log( 'hello' )
}
</script>

then, ComponentA can do:

<script setup>
const componentb = ref(null)

componentb.value.internal_function()
</script>

and hello will be logged to the console.

1 Comment

This shoul dbe the answer for Vue3
1

With Vue3 you need to:

Parent component:

    <template>
      <ChildComponent @created="handleCreate" />
    </template>
    export default {
      methods: {
        handleCreate() {
          console.log('Child has been created.');
        }
      }
    }

Child Component:

    // ChildComponent
    export default {
      created() {
        this.$emit('created');
      }
    }

Comments

0

For those looking > 2024 vue 3 composition.

// child

const emit = defineEmits(['close_chat']);

const close_chat = () => {
   emit('close_chat');
};


//parent

import ChatBot from './components/chatbot.vue';

const close_chat = () => {
   console.log('closed');
}

// <ChatBot  @close_chat="close_chat"></ChatBot>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.