Monday, June 3, 2024
 Popular · Latest · Hot · Upcoming
87
rated 0 times [  94] [ 7]  / answers: 1 / hits: 7346  / 5 Years ago, wed, june 12, 2019, 12:00:00

I have following problem, which I don't know how to properly tackle.



I have list of all purchased images on my view. I display them with v-for loop. Each image also has progress-bar element, so when user clicks on download button, downloadContent function gets executed and progress bar should be displayed.



So my html looks like this.



<section class=stripe>
<div class=stripe__item card v-for=(i, index) in purchasedImages>
<progress-bar :val=i.download_progress
v-if=i.download_progress > 0 && i.download_progress < 100></progress-bar>
<div class=card__wrapper>
<img :src='/'+i.thumb_path class=card__img>
</div>
<div class=btn-img card__btn card__btn--left @click=downloadContent(i.id_thumb, 'IMAGE', index)>
</div>
</div>
</section>


And this is my JS Code



import Vue from 'vue'
import orderService from '../api-services/order.service';
import downloadJs from 'downloadjs';
import ProgressBar from 'vue-simple-progress';

export default {
name: MyLocations,
components: {
ProgressBar: ProgressBar
},
data() {
return {
purchasedImages: {},
purchasedImagesVisible: false,
}
},
methods: {
getUserPurchasedContent() {
orderService.getPurchasedContent()
.then((response) => {
if (response.status === 200) {

let data = response.data;
this.purchasedImages = data.images;

if (this.purchasedImages.length > 0) {
this.purchasedImagesVisible = true;
// Set download progress property
let self = this;
this.purchasedImages.forEach(function (value, key) {
self.purchasedImages[key].download_progress = 0;
});
}
}
})
},
downloadContent(id, type, index) {
let self = this;
orderService.downloadContent(id, type)
.then((response) => {
let download = downloadJs(response.data.link);
download.onprogress = function (e) {
if (e.lengthComputable) {
let percent = e.loaded / e.total * 100;
let percentage = Math.round(percent);
if (type === 'IMAGE') {
// Is this proper way to set one field reactive?
self.purchasedImages[index].download_progress = percentage;
if (percentage === 100) {
self.purchasedImages[index].download_progress = 0;
}
}
}
}
})
},
},
mounted: function () {
this.getUserPurchasedContent();
}
};


So the problem is. When user clicks on download button, download starts to execute and I get downloaded content, but I don't see progress bar. So I wonder, is this a proper way to set element reactive? How should my implementation look like? How to properly set self.purchasedImages[index].download_progress object key value, so progress bar will be visible?



If you need any additional informations, please let me know and I will provide. Thank you!


More From » vue.js

 Answers
7

The snippet:


this.purchasedImages = data.images;

Leads us to believe data.images is an array of objects that do not have the download_progress property. So Vue can't detect/react when it changes.


To fix that, you can use Vue.set:


Vue.set(self.purchasedImages[key], 'download_progress', 0);

This is very well explained in Vue.js docs.




Another option: add the property before assigning to data


Just for completeness, you could also add the download_progress before assigning the array to the data property. This would allow Vue to notice it and be able to react to it.


Example:


let data = response.data;
this.purchasedImages = data.images.map(i => ({...i, download_progress: 0}));

if (this.purchasedImages.length > 0) {
this.purchasedImagesVisible = true;
// no need to set download_progress here as it was already set above
}

// if above could also be simplified to just:
this.purchasedImagesVisible = this.purchasedImages.length;






On a side note, since it is gonna be an array and not an object, I suggest you declare it as such:


data() {
return {
purchasedImages: [], // was: {},

This will have no effect, since you overwrite purchasedImages completely in (this.purchasedImages = data.images;), but it is a good practice as it documents that property's type.


[#7322] Tuesday, June 11, 2019, 5 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
kevonmoisesf

Total Points: 693
Total Questions: 101
Total Answers: 128

Location: Reunion
Member since Mon, Dec 28, 2020
4 Years ago
;