Piotr Żak
Piotr Żak

Reputation: 2423

vue reload child component

I'm using vue, version 2.5.8

I want to reload child component's, or reload parent and then force children components to reload.

I was trying to use this.$forceUpdate() but this is not working.

Do You have any idea how to do this?

Upvotes: 34

Views: 60886

Answers (6)

Alex Montoya
Alex Montoya

Reputation: 5119

This example is from the link that @sureshvv shared

import Vue from 'vue';
Vue.forceUpdate();

// Using the component instance
export default {
methods: {
  methodThatForcesUpdate() {
    // ...
    this.$forceUpdate();  // Notice we have to use a $ here
    // ...
   }
  }
} 

Upvotes: 2

Bagaskara
Bagaskara

Reputation: 891

Add key to child component, then update the key in parent. Child component will be re-created.

<childComponent :key="childKey"/>

Upvotes: 21

omarjebari
omarjebari

Reputation: 5519

I've found that when you want the child component to refresh you either need the passed property to be output in the template somewhere or be accessed by a computed property.

<!-- ParentComponent -->
<template>
    <child-component :user="userFromParent"></child-component>
</template>

<!-- ChildComponent -->
<template>
    <!-- 'updated' fires if property 'user' is used in the child template -->
    <p>user: {{ user.name }}
</template>
<script>
export default {
    props: {'user'},
    data() { return {}; }
    computed: {
        // Or use a computed property if only accessing it in the script
        getUser() {
            return this.user;
        }
    }
}
</script>

Upvotes: 0

sureshvv
sureshvv

Reputation: 4422

Use a :key for the component and reset the key.

See https://michaelnthiessen.com/force-re-render/

Upvotes: 50

Piotr Żak
Piotr Żak

Reputation: 2423

I'm using directive v-if which is responsible for conditional rendering. It only affects reloading HTML <template> part. Sections created(), computed are not reloaded. As I understand after framework load components reloading it is not possible. We can only re render a <template>.

Rerender example.

I have a Child.vue component code:

<template>
    <div v-if="show">
      Child content to render 
      {{ callDuringReRender() }}
    </div>
</template>

<script>
    export default {
        data() {            
            return {               
                show: true
            }
        }
        ,
        methods: {
            showComponent() {
                this.show = true
            },
            hideComponent() {
                this.show = false
            },
            callDuringReRender() {
                console.log("function recall during rendering")
            }
        }
}
</script>

In my Parent.vue component I can call child methods and using it's v-if to force the child rerender

<template>
    <div>
      <input type="button" 
       value="ReRender the child" 
       @click="reRenderChildComponent"/>

      <child ref="childComponent"></child>

    </div>
</template>

<script>
    import Child from './Child.vue'

    export default {
       methods: {
            reRenderChildComponent(){
                this.$refs.childComponent.hideComponent();
                this.$refs.childComponent.showComponent()
            }
       },
       components: {
            Child
       }
    }
</script>

After clicking a button in console You will notice message "function recall during rendering" informing You that component was rerendered.

Upvotes: 3

Roy J
Roy J

Reputation: 43899

If the children are dynamically created by a v-for or something, you could clear the array and re-assign it, and the children would all be re-created.

To simply have existing components respond to a signal, you want to pass an event bus as a prop, then emit an event to which they will respond. The normal direction of events is up, but it is sometimes appropriate to have them go down.

new Vue({
  el: '#app',
  data: {
    bus: new Vue()
  },
  components: {
    child: {
      template: '#child-template',
      props: ['bus'],
      data() {
        return {
          value: 0
        };
      },
      methods: {
        increment() {
          this.value += 1;
        },
        reset() {
          this.value = 0;
        }
      },
      created() {
        this.bus.$on('reset', this.reset);
      }
    }
  }
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<div id="app">
  <child :bus="bus">
  </child>
  <child :bus="bus">
  </child>
  <child :bus="bus">
  </child>
  <button @click="() => bus.$emit('reset')">Reset</button>
</div>

<template id="child-template">
  <div>
  {{value}} <button @click="increment">More!</button>
  </div>
</template>

Upvotes: 6

Related Questions