Calling method on Child Component - Composition API
Asked Answered
E

3

24

I have a parent component where I need to call a method that exists in one of its child components:

<template>
  <div>
    <button @click="callChildMethod">
    <child-component ref="child" />
  </div>
</template>
<script>
  setup(props) {
    const child = ref(null)
    const callChildMethod = () => {
      child.doSomething()
    }

    return {
      child,
      callChildMethod
    }
  }
</script>
  

The child component contains the doSomething method:

const doSomething = () => { console.log('calling method....') }

Since I'm using the VueJS3 and the Composition API, my approach was to use a template ref to call the method in the child component. Obviously is not working but I can't see what I'm missing. Does someone have a clue about this one? Thanks in advance

Exculpate answered 18/11, 2020 at 8:48 Comment(0)
N
19

You're missing the value field in your ref, it should be :

 const callChildMethod = () = {
  child.value.doSomething()
}

Edit amazing-cori-5hgi9

If the child component is defined using the script setup syntax you should use defineExpose to expose the method to the outside

<script setup>

function doSomething(){
  //......
}

defineExpose({
  doSomething,
});

</script>

Parent :

<template>
  <div>
    <button @click="callChildMethod">
    <child-component ref="child" />
  </div>
</template>
<script>
  setup(props) {
    const child = ref(null)
    const callChildMethod = () => {
      child.doSomething()
    }

    return {
      child,
      callChildMethod
    }
  }
</scrip>

or

<template>
  <div>
    <button @click="callChildMethod">
    <child-component ref="child" />
  </div>
</template>
<script setup>

    const child = ref(null)
    const callChildMethod = () => {
      child.doSomething()
    }


</scrip>
Nigrify answered 18/11, 2020 at 9:1 Comment(2)
The function statement const callChildMethod = () = { should be const callChildMethod = () => { in that whay it becomes an arrow-functionGinger
Getting an error "child.doSomething is not a function", on latest play.vuejs.orgChickamauga
T
58

P.s. for <script setup> (Composition API) need to use defineExpose

https://v3.vuejs.org/api/sfc-script-setup.html#defineexpose

Parent component:

<script setup>
...
const childred = ref();

childred.value.doSomething()
</script>

<template>
  <ChildrenComponent ref="childred" />
</template>

ChildrenComponent:

<script setup>
...
function doSomething(){
  console.log(1);
}

defineExpose({
  doSomething,
});

</script>

<template>
  <div>123</div>
</template>

Tighten answered 4/12, 2021 at 19:50 Comment(5)
Great, when using script setup syntax just we have to do this wayNikitanikki
thanks a lot man! All day I was searching for a solution. nobody mentioned defineExpose!!!! you are the best!!!!!!!Cranium
Seems not working on Vue 3 5.0.8 Composition API <script setup>, error: Cannot read properties of undefined (reading 'doSomething')Chickamauga
@BassemRamzy seems like a problem with your componentsAcherman
@BassemRamzy I had exactly the same problem. The only way I made it work was to inspect the ref object and I found that you can call the function from childred.value.$.exposed.doSomething()Musk
N
19

You're missing the value field in your ref, it should be :

 const callChildMethod = () = {
  child.value.doSomething()
}

Edit amazing-cori-5hgi9

If the child component is defined using the script setup syntax you should use defineExpose to expose the method to the outside

<script setup>

function doSomething(){
  //......
}

defineExpose({
  doSomething,
});

</script>

Parent :

<template>
  <div>
    <button @click="callChildMethod">
    <child-component ref="child" />
  </div>
</template>
<script>
  setup(props) {
    const child = ref(null)
    const callChildMethod = () => {
      child.doSomething()
    }

    return {
      child,
      callChildMethod
    }
  }
</scrip>

or

<template>
  <div>
    <button @click="callChildMethod">
    <child-component ref="child" />
  </div>
</template>
<script setup>

    const child = ref(null)
    const callChildMethod = () => {
      child.doSomething()
    }


</scrip>
Nigrify answered 18/11, 2020 at 9:1 Comment(2)
The function statement const callChildMethod = () = { should be const callChildMethod = () => { in that whay it becomes an arrow-functionGinger
Getting an error "child.doSomething is not a function", on latest play.vuejs.orgChickamauga
C
2

Using ref generates an error with me, I found out another handshaking way (using watch for a property set by a reactive variable in parent, emitting back the results) that's fine with me, and gives more control, in case needed:

Child Component:

const props = defineProps({
  callRequested: {
    type: Boolean,
  },
});
function myFunc() {
  let result = false ;
  // Do your stuff
  return result;
}
const emit = defineEmits(['funcResult']);
watch(
  () => props.callRequested,
  (newVal) => {
    console.log(`newVal is: ${newVal}`);
    if (newVal)
      emit('funcResult', myFunc());
  }
)

Parent Component:

<template>
  <div>
    <button @click="callChildMethod">
    <child-component 
     :call-requested="state.callRequested" 
     :@func-result="funcResult"
    />
  </div>
</template>
<script setup>
const state = reactive({
  callRequested: false,
});
function callChildMethod() {
  state.callRequested= true;
}
function funcResult(param) {
  state.callRequested = false;  // Reset it for next call
  // Do parent stuff based on param = function result
}
</script>
Chickamauga answered 12/2, 2023 at 10:36 Comment(1)
ref worked with me only after I defineExpose a variable (in addition to the function).Chickamauga

© 2022 - 2024 — McMap. All rights reserved.