Search code examples
vue.jsvuejs2vue-componentrendering

Firing child method from parent vue 2


I am trying to represent a list of components defined in an array.

I need to fire child component method from parent.

I know that ref can be used to achieve this purpose, but my component is being rendering dynamically and I don't know how to encode that expression.

Im try this (code segment to explain the idea):

const childPaciente = ref()
.
.
onMounted:() => {
    childPaciente.value.submit()
}
  

The goal is that when the next button is clicked:

<button v-if="formPosition < patientProcess.length - 1" >
              Next            
</button>

the method of the child component fires:

methods: {
    submit() {
      //do something
}

This is my component array definition:

    import PacNew from '@/components/emp/global/PacNew.vue'
    import Step2 from '@/components/emp/global/Step2.vue'
    import Step3 from '@/components/emp/global/Step3.vue'
    import { ref } from 'vue'
    
    
    const childPaciente = ref()
    
    
    export default {
      data() {
        return {
          formPosition: 0,
          animation: 'animate-in',
          datosPaciente:[],
          patientProcess: [
// NEW DEFINITION
      patientProcess: [
        { step: 1, visible: true, title: 'Subsection1', component: PacienteNuevo, comp:PacienteNuevo },
        { step: 2, visible: false, title: 'Subsection2', component: Step2, comp:Step2  },
        { step: 3, visible: false, title: 'Subsection3', component: Step3, comp:'' },
      ]        
}
      },
      mounted() {
        console.log(this.$refs.comp)
      },
      components: {
        PacNew,
        Step2,
        Step3
      },

This is my code to render the components array:

 <section :class="animation">
              <h2>{{ patientProcess[formPosition].title }}</h2>
    
              <div>
                <div v-for="(tab, index) in patientProcess" :key="'component' + index">
                  <component v-if="patientProcess[index].visible" v-bind:is="tab.component" ref="comp">
                  </component>
                </div>
    
                <vs-tab v-for="(tab, index) in patientProcess" :label="tab.title" :key="index">
                  <component v-bind:is="tab.component">
                  </component>
                </vs-tab>
              </div>
              <div>
                <button v-if="formPosition < patientProcess.length - 1" >
                  Next
                </button>
                <button v-if="formPosition === patientProcess.length - 1">
                  Enter
                </button>
                <button v-if="formPosition < patientProcess.length && formPosition > 0" @click="prevStep">
                  Previous
                </button>
              </div>
    </section>

how can i achieve this.

Regards...


Solution

  • Using ref the way you are is more akin to using refs with Vue 3's Composition API and <script setup> tag, rather than Vue 2's Options API.

    With the Options API you just need to add the ref property to the component in your template, then you can access it in your methods with this.$refs. This is documented in the Vue 2 docs under Accessing Child Component Instances & Child Elements

    When the same ref is attached to multiple elements like with v-for, the this.$refs will hold an array of all elements with that same ref.

    <div v-for="(tab, index) in patientProcess">
      <component v-bind:is="tab.component" ref="comp">
    </div>
    

    Again you've mixed up Vue 3 Composition API and Options API when it comes to calling the mounted hook. It's onMounted:() => {} with Composition API, mounted() {} with Options API

    // correct way to call mounted hook in Vue 2
    mounted() {
      console.log(this.$refs.comp) // logs "[VueComponent, VueComponent, VueComponent]"
    }
    

    You can then search the array to find the specific component needed and call the desired method, or reference the exact index needed:

    this.$refs.comp[0].submit()