3

Below is a code for a header and a body (different components). How do you call the continue function of the component 2 and pass a parameter when you are inside component 1, using composition API way...

Component 2:

export default {
    setup() {
        const continue = (parameter1) => {
            // do stuff here
        }
        
        return {
            continue
        }
    }
}

enter image description here

3
  • You can use this.$parent in the component to access it's parents instance Commented May 13, 2022 at 3:57
  • 1
    @power-cut You can but you shouldn't. It was a bad practice in AngularJS, where $parent came from to Vue Commented May 13, 2022 at 6:39
  • @EstusFlask I completely agree. But nothing exists without a reason. There are many ways to achieve the same thing. Commented May 13, 2022 at 8:04

2 Answers 2

9

Here is how I solved it with script setup syntax:

Parent:

<script setup>
import { ref } from 'vue';

const childComponent = ref(null);

const onSave = () => {
    childComponent.value.saveThing();
};
</script>

<template>
    <div>
        <ChildComponent ref="childComponent" />

        <SomeOtherComponent
            @save-thing="onSave"
        />
    </div>
</template>

ChildComponent:

<script setup>
const saveThing = () => {
    // do stuff
};

defineExpose({
    saveThing,
});
</script>

It doesn't work without defineExpose. Besides that, the only trick is to create a ref on the component in which you are trying to call a function.

In the above code, it doesn't work to do @save-thing="childComponent.saveThing", and it appears the reason is that the ref is null when the component initially mounts.

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

Comments

5

One way to solve this is to use events for parent-to-child communication, combined with template refs, from which the child method can be directly called.

  1. In ComponentB.vue, emit an event (e.g., named continue-event) that the parent can listen to. We use a button-click to trigger the event for this example:
<!-- ComponentB.vue -->
<script>
export default {
  emits: ['continue-event'],
}
</script>

<template>
  <h2>Component B</h2>
  <button @click="$emit('continue-event', 'hi')">Trigger continue event</button>
</template>
  1. In the parent, use a template ref on ComponentA.vue to get a reference to it in JavaScript, and create a function (e.g., named myCompContinue) to call the child component's continueFn directly.
<!-- Parent.vue -->
<script>
import { ref } from 'vue'

export default {
  ⋮
  setup() {
    const myComp = ref()
    const myCompContinue = () => myComp.value.continueFn('hello from B')

    return {
      myComp,
      myCompContinue,
    }
  },
}
</script>

<template>
  <ComponentA ref="myComp" />
  ⋮
</template>
  1. To link the two components in the parent, use the v-on directive (or @ shorthand) to set myCompContinue as the event handler for ComponentB.vue's continue-event, emitted in step 1:
<template>
  ⋮
  <ComponentB @continue-event="myCompContinue" />
</template>

demo

Note: Components written with the Options API (as you are using in the question) by default have their methods and props exposed via template refs, but this is not true for components written with <script setup>. In that case, defineExpose would be needed to expose the desired methods.

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.