I’m building a simple file upload to get familiar with Aurelia and ran into this seemingly simple issue.
If you just want to see a quick example of the issue, https://gist.run/?id=e04b44bf6fd5c53668517fb9c5faaa04
Say I have an array of files and an array of uploadProgresses. In my view, I have
<li repeat.for='file in files'>${file.name} - ${uploadProgresses[$index]}</li>
I want this to be updated whenever the uploadProgresses changes. However, repeat.for doesn’t seem to watch other VM collections (works for primitives).
Currently, I have 3 solutions:
-
Merge both arrays into an array of objects (file, progress) and just use it in repeat.for. It works but requires this higher level array
-
Aurelia gitter suggested using a signal whenever uploadProgresses changes. Again it works but this has extra boilerplate
-
@Alexander-Taran suggested reassigning the array with a modified temp array. For example:
const newRandoms = this.randoms.slice()
newRandoms.splice(1, 1, Math.random())
this.randoms = newRandoms
https://gist.run/?id=e04b44bf6fd5c53668517fb9c5faaa04
This works but it seems inconsistent with other observable or binding behaviors. Using splice should work as well?
I am wondering if there’s a better way to achieve this or am I missing something basic?
uploadProgresses[$index]
expression will be updated when either uploadProgresses
or $index
changes.
----- Update:
You already stated the following snippet in your post. Sorry I didn’t read carefully
To work around this, I suggest use different model. The model can be a wrapper for both the file and uploading progress, this way, it works better and helps group your data better;
class FileUploadModel {
constructor(file) {
this.file = file;
// other fields
// ...
// listen to progress event
this.progress = 0;
}
}
class App {
constructor() {
this.uploads = [];
}
onSelectFiles(files) {
for (let i = 0, ii = files.length; ii > i; ++i) {
this.uploads.push(new FileUploadModel(file));
}
}
}
<template>
<input type='file' multiple change.trigger='onSelectFiles($event.target.files)' />
<ul>
<li repeat.for='upload of uploads'>
# ${$index} Time - ${upload.estimateUploadTime} <-> Random - ${upload.progress }
</li>
</ul>
<h2>Randoms</h2>
</template>
gist https://gist.run/?id=93563c62b0d964a0b622d163ceea580d
2 Likes
Sorry if I wasn’t clear. This is similar to the first solution with the added benefit of using a class. So far I like this solution the best although I still wonder if we can do something to make it just work. But I still don’t know enough about Aurelia to guess why this wouldn’t just work - particularly why reassigning works but splice doesn’t.
@lovetostrike take the win (-:
or pretty soon you’ll want to add a third array for another property of the “object”.
2 Likes