Have Parent Component Wait till Child has emitted data back to parent ? (Using Vue 2)

Viewed 36

Context -
I have a large form that I've broken up into components. I'm going to focus on only one parent/child component relationship for brevity here.

Doing some validation on each child component. Emitting back to parent when a submit button is clicked on the parent.

I have a submit button on the parent. When clicked I am emitting all child component data back to the parent

I have a method on the parent that receives the emitted data. As well as an object instantiated on the parent data() method to assign to the incoming data.

Problem - When you hit submit, the emitted data is present on the child component, but it's empty on the parent. The submit method finishes before the emitting method finishes.

Is there a best way of accomplishing this?

I could take all inputs and put them in one giant form.. but I hate that approach. I've tried setTimeout for a brief second. This seems to work at times, but it feels so hacky. I delay the submit method from finishing.. allowing the emit to finish.. that just doesn't feel sustainable or right.

Is there a clear way of doing this? Thank you so much for the assistance.

  <1-- Parent -->
 <template>
        <!-- CHILD -->
        <LabExposureType v-if="lab" 
              @passLabExposureToParent="exposureOnSubmit">
        </LabExposureType>
      <div class="submitAndClear d-flex justify-center pb-3">
          <v-btn color="success" class="mr-4" @click="submit">submit</v-btn>
      </div>
</template>
    data(){
    exposureVals:{},      
    }
    //Removed some data and others for brevity
    methods:{
              submit() {
                  //collect vals before doing this
                  //Exposure values
                  console.log('emitted exposure vals', this.exposureVals); <- this of course is empty has the below has not finished
                 },
              //Emitted method
              exposureOnSubmit(input) {
                    this.exposureVals = input
                 }
    
          }

EDIT - Added code for more clarity

Parent -

<LabExposureType v-if="lab" :labState="exposureState" v-model="standardNum" 
    @passLabExposureToParent="exposureOnSubmit">
</LabExposureType> 

CHILD -

   <v-text-field v-if="this.isStandardMethod" v-model="standardNum" label="Organization and Standard Number"
        class="text-caption primary--text" required :error-messages="standardNumErrors" 
        :value="modelValue" @input="$emit('update:modelValue', $event.target.value)"
        @blur="$v.standardNum.$touch()"></v-text-field>

props and emits -

  props: [ "labState", "modelValue"],
  emits:['update:modelValue'],
1 Answers

Your child components should emit their values before the submit is ever clicked. Best practice is to use the v-model directive so that the parent always has the latest value of the child. Define the v-model name on the parent with whatever name you want, just make sure the prop name in the child component is named modelValue and that the value is emitted using event update:modelValue:

<!-- Parent -->
<child v-model="searchText" />
<!-- Child -->
<script>
export default {
  props: ['modelValue'],
  emits: ['update:modelValue']
}
</script>

<template>
  <input
    :value="modelValue"
    @input="$emit('update:modelValue', $event.target.value)"
  />
</template>
Related