Search code examples
javascriptvue.jsvuejs3pinia

How to call a method from a distinct component using Vue 3 & Pinia


I want to call an inner function of a component if I click a button. There are many suggestions using shared data, but it should work separately for different components. Here's an example:

// Page.vue
<template>
    <MyComponent my-prop="abc"/>
    <button @click="???">ButtonX</button>

    <MyComponent my-prop="123"/>
    <button @click="???">ButtonY</button>
</template>
// ...
// MyComponent.vue:
<script>
    function foo() {
        //Do something inside this component
    }
</script>
// ...

My goal is that if I press ButtonX then foo() function called for <MyComponent my-prop="abc"/> but if I press ButtonY the same inner foo() function runs for <MyComponent my-prop="123"/>. How could I achieve that? (The components could be far from each other in the component tree.)

I prefer solution using only Vue 3 and Pinia.


Solution

  • You can use ref:

    <template>
      <MyComponent myProp="abc" ref="a" />
      <button @click="handle('a')">ButtonX</button>
    
      <MyComponent myProp="123" ref="b" />
      <button @click="handle('b')">ButtonY</button>
    </template>
    
    <script>
    import { ref } from "vue";
    import MyComponent from "./MyComponent.vue";
    
    export default {
      components: {
        MyComponent,
      },
      setup() {
        const a = ref(null);
        const b = ref(null);
    
        const handle = (refName) => {
          const ref = refName === "a" ? a : b;
          ref.value.foo();
        };
    
        return {
          a,
          b,
          handle,
        };
      },
    };
    </script>