forceUpdate when component take props VueJS

I need to pass the id parameter to my component and call its update (re-rending -> without reloading the page)

i have a component with avatars loading method

settings.vue

<template>
... download form and button with onUploadImg method 
</template>

<script>

methods: {
    onUploadImg() {
        if(this.avatarFile == null) return;
        var formData = new FormData();
        formData.append("file", this.avatarFile);        
        axios.post('urlForPost',
          formData,
          {
            headers: {
              'Content-Type': 'multipart/form-data'
            }
          })
          .then(response => {
              //response Ok, show message and reload img on this page
               this.$nextTick(() => {
                   //Need send new FileId from image to MyVueAvatar.vue and update him
                   localStorage.setItem('picture', response.data); //can be through local storage?
               })
            })
            .catch(error => {
                 console.log(error);
      });
    }
}
</script>

OrderContainer.vue

<template>
    <my-vue-avatar class="img-avatar" :id="this.avatarPicId"></my-vue-avatar>
....
</template>
<script>
import MyVueAvatar from '../Avatar'
....
</script>

MyVueAvatar.vue (need to update this component if a new avatar has been uploaded to settings.vue)

<template>
    <div>
        <img :src="`data:image/png;base64, ${file}`" class="img-avatar" style="height: 35px;"  />
    </div>
</template>

<script>
import axios from 'axios'
export default  {
    props: {
        id: null
    },
    data: () => {
        return { 
            file: null
        }
    },
    created() {
        this.onGetImage(this.id);
    },
    methods: {
        onGetImage(id) {
            if (id == null) return;        
            axios.defaults.headers.common['Authorization'] = 'Bearer ' + localStorage.getItem('jwt');
            axios.get('url/File/Get/' + id,
            {
                responseType: 'arraybuffer'
            })
            .then(r =>
            {
                var buffer = new Buffer(r.data, 'binary').toString('base64');
                this.file = buffer;
            })
            .catch(error => {
                console.log(error);
            });
        }
    }
}
</script>

how can do this?

Upvotes: 2

Views: 1381

Answers (1)

Efrat Levitan
Efrat Levitan

Reputation: 5632

the props you are passing to MyVueAvatar are supposed to be reactive. if you still want to cause a complete re-rendering of MyVueAvatar every time avatarPicId changes, its a little hacky, but you can use v-if directive to cause late rendering/ re-render your child component:

to establish a connection between settings.vue and orderContainer.vue, you have a few options to do that, here's an example using vue eventBus:

inside Settings.vue, whenever id changes:

this.$eventBus/*or whatever you named your eventBus*/.$emit('idChange',id);

and on the other side, orderContainer.vue will listen to this change:

//OrderContainer.vue

    <template>
        <my-vue-avatar v-if="hasID" class="img-avatar" :id="avatarPicId"></my-vue-avatar>
    ....
    </template>
    <script>
    import MyVueAvatar from '../Avatar'
    ....
    data(){
            return { 
                avatarPicId:'',
                hasID: false
            }
        },
    beforeMount(){
        this.$eventBus.$on('idChange',id => {
            //this fanction will get triggered every time an `idChange` event fires.
            //lets assign the new value to our `avatarPicId`:
            this.avatarPicId = id;
            this.hasID = !!this.avatarPicId; //assign a boolean to this.hasID, wether the accepted id isnt undefined,null,false or empty string.
            //this.avatarPicId is sent as props to `my-vue-avatar` child component.
            //it should re-evaluates itself. if its not happening, you can  
             //cause here a complete destruction of MyVueAvatar 
             //component:
              this.hasID = false;
              //and a re-rendering, after the destruction is completed:
              this.$nextTick(()=> this.hasID = true);
        })
    },
}
</script>

Upvotes: 2

Related Questions