3

My parent component like this :

<template> 
    <div ref="modal" class="modal" tabindex="-1" role="dialog">
        <div class="modal-dialog" role="document">
            <div class="modal-content modal-content-data">
                <form id="form-data">
                    ...
                    <location-select .../>
                    ...
                </form>
            </div>
        </div>
    </div>
</template>
<script>
    import LocationSelect from './LocationSelect.vue'
    export default{
        name: 'CartModal',
        components:{
            LocationSelect,
        },
        mounted(){
            $(this.$refs.modal).on('hidden.bs.modal', () => {
                Object.assign(this.$data, this.$options.data())
            })
        }
    }
</script>

If modal hidden, it will reset data in parent component and it works

I want to reset data also in child component

I try like this :

<template>
    <select class="form-control" v-model="selected" ...>
        ...
    </select>
</template>
<script>
    export default{
        name: 'LocationSelect',
        ...
        created() {
            $(this.$parent.$refs.modal).on('hidden.bs.modal', () => {
                Object.assign(this.$data, this.$options.data())
            })
        }
    };
</script>

But it does not work

The child component no reset the data

How can I solve this problem?

1
  • Pass the data using props. Then you can have control on it Commented Sep 11, 2017 at 16:36

1 Answer 1

3

The main problem with this code is the handler in LocationSelect is being added before this.$parent.$refs.modal exists. A ref does not exist until the component is mounted.

The easiest way to solve this would be to move the code to mounted.

mounted() {
  $(this.$parent.$refs.modal).on('hidden.bs.modal', () => {
    Object.assign(this.$data, this.$options.data())
  })
}

Or you could leave it in created and use nextTick.

created() {
  this.$nextTick(() => {
    $(this.$parent.$refs.modal).on('hidden.bs.modal', () => {
      Object.assign(this.$data, this.$options.data())
    })
  })
}

Another way to handle this would be to add a ref to the LocationSelect component and add a method that clears it that can be called from the parent. In LocationSelect add this method:

methods:{
  clear(){
    Object.assign(this.$data, this.$options.data())
  }
}

In the parent template add a ref:

<location-select ref="locationSelect" ... />

And in your parent's mounted:

mounted(){
  $(this.$refs.modal).on('hidden.bs.modal', () => {
    Object.assign(this.$data, this.$options.data())
    this.$refs.locationSelect.clear()
  })
}

However, the most idiomatic way to handle this with Vue would be to modify the component to support v-model and then it would be automatically cleared when the parent is cleared.

<template>
    <select class="form-control" v-model="selected" ...>
        ...
    </select>
</template>
<script>
    export default {
        props: ["value"],
        name: 'LocationSelect',
        computed:{
          selected:{
            get(){ return this.value },
            set(v) { this.$emit('input', v) }
          }
        },
    };
</script>

And then in the parent template:

<location-select v-model="someDataValue" ... />

If you did this, then when the parent is clear, the child is automatically cleared as well.

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

14 Comments

Why would you use nexttick in created rather than moving it to mounted?
@RoyJ Child mounted fires before parent mounted. See here. codepen.io/Kradek/pen/dVbzJg?editors=1010
@RoyJ But the $ref does appear to exist at that point in the parent...
Do you still have some leftover old answer in your revised answer?
@RoyJ Probably a confusing sentence or two. Updated.
|

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.