Not too long ago file input binding was added to Aurelia by @PWKad. In this post I'm going to cover how you would use file input binding.
HTML File Input
The markup for a typical file input looks like this:
<input type="file">
If you want to allow users to choose multiple files, add the multiple
attribute:
<input type="file" multiple>
You can restrict allowable file types using the accept
attribute:
accept
If the value of the type attribute is file, this attribute indicates the types of files that the server accepts; otherwise it is ignored. The value must be a comma-separated list of unique content type specifiers:
- A file extension starting with the STOP character (U+002E). (E.g.: ".jpg,.png,.doc")
- A valid MIME type with no extensions
- audio/* representing sound files HTML5
- video/* representing video files HTML5
- image/* representing image files HTML5
- MDN
Example:
<input type="file" accept="image/*">
<input type="file" accept=".txt,.csv">
Binding to a file input
Aurelia supports binding to an input's files property, which is of type FileList
:
<input type="file" files.bind="selectedFiles">
In this example, when the user selects a file the value of the input's files
property would be assigned to the view-model's selectedFiles
property.
Displaying the selected files
Consider an file input that accepts image files:
<input type="file" multiple accept="image/*" files.bind="selectedFiles">
How would we display the selected files?
Aurelia's repeat.for
binding command supports arrays, maps and numbers, but not FileList objects. We can use a converter to translate a FileList to an Array:
export class FileListToArrayValueConverter {
toView(fileList) {
let files = [];
if (!fileList) {
return files;
}
for(let i = 0; i < fileList.length; i++) {
files.push(fileList.item(i));
}
return files;
}
}
Items in the FileList object are of type File, which inherits from the Blob object. We need to convert the blob to a data url so we can display it in an img tag:
export class BlobToUrlValueConverter {
toView(blob) {
return URL.createObjectURL(blob);
}
}
Bringing it all together, here's what the view and view-model look like:
<template>
<input type="file" multiple accept="image/*" files.bind="selectedFiles">
<ul>
<li repeat.for="file of selectedFiles | fileListToArray">
<h1>${file.name}: ${file.type} ${file.size / 1000} kb</h1>
<img src.bind="file | blobToUrl"><img>
Last Modified: ${file.lastModifiedDate}
</li>
</ul>
</template>
export class App {
selectedFiles;
}
Here's a live example: