7
votes

I have a parent component and a child component. The child component is inside a dialog in the parent component. And this dialog is shown or hidden.

my parent component

<template>
    <div>
        <v-dialog v-model="dialog">
            <product-form></product-form>
        </v-dialog>
    </div>
</template>

my child component (product-form)

<template>
  <div>
    .....
    <input type="text" v-model="data">
    .....
  </div>
</template>
<script>
  export default {

    data: () => ({
        data: '',
    }),
    methods:{

      onSubmitProduct(){

        //send data to server        
      }
    },
}
</script>

I need to clear the child form whenever the dialog is shown. The problem is that I display the dialog through the parent component. NOTE: I do not want to use v-model in the child component because I need to send the data to the server from the child component and not the parent component.

Can someone help me?

* **SOLUTION ***

I was able to solve the problem using ref. I don't know if my solution is contrary to good practices. But it was the best I could.

//parent component
<template>
    <div>
        <v-dialog v-model="dialog">
            <product-form ref="childComponent"></product-form>
        </v-dialog>
    </div>
</template>

this.$refs.childComponent.resetForm();

-

//child compopnent
<template>
  <div>
    .....
    <input type="text" v-model="data">
    .....
  </div>
</template>
<script>
  export default {

    data: () => ({
        data: '',
    }),
    methods:{

      onSubmitProduct(){

        //send data to server        
      },
      resetForm(){
        //code to reset form
      }
    },
}
</script>
3

3 Answers

1
votes

You should probably pass a bus as a prop to the child. Then you can emit an event that the child can act on.

new Vue({
  el: '#app',
  data: {
    showing: false,
    bus: new Vue()
  },
  methods: {
    toggleDialog() {
      this.showing = !this.showing;
      this.bus.$emit('reset');
    }
  },
  components: {
    productForm: {
      template: '#product-form-template',
      props: ['bus'],
      data() {
        return {
          value: 'you will never see this'
        }
      },
      methods: {
        resetForm() {
          this.value = 'Form was reset';
        }
      },
      created() {
        this.bus.$on('reset', this.resetForm);
      }
    }
  }
});
.dialog {
  outline: 2px solid blue;
  height: 200px;
}
<script src="//unpkg.com/vue@latest/dist/vue.js"></script>
<div id="app">
  <button @click="toggleDialog">Toggle dialog</button>
  <div class="dialog" v-show="showing">
    <product-form :bus="bus"></product-form>
  </div>
</div>

<template id="product-form-template">
  <div>
    Type something here: <input v-model="value">
  </div>
</template>
1
votes

You should use the event emitter for parent-child communication. In your child template listen for an event:

<template>
    <div>
        <v-dialog v-model="dialog">
            <product-form @dialog-shown="clearForm"></product-form>
        </v-dialog>
    </div>
</template>

And in your parent emit the event:

this.$emit('dialog-shown');
1
votes

Using the solution of @Renato souza de Oliveira, you can reset with Object.assign(this.$data, this.$options.data())

For example

Child component

<template>
  <div>
    .....
  </div>
</template>
<script>
  export default {

    data: () => ({
        ....
    }),
    methods:{ ... },
  }
</script>

Parent Component

<template>
    <div>
        <v-dialog v-model="dialog">
            <child-name ref="childComponent"></child-name>
        </v-dialog>
    </div>
</template>
<script>
  export default {
     ....,
     methods:{
        ....,
        resetChild(){
          const ref = this.$refs.childComponent
          Object.assign(ref.$data, ref.$options.data());
  
        }
     }
}

</script>