Binding to file inputs with Aurelia

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:

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



<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++) {
    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:

  <input type="file" multiple accept="image/*" files.bind="selectedFiles">

    <li repeat.for="file of selectedFiles | fileListToArray">
      <h1>${}: ${file.type} ${file.size / 1000} kb</h1>
      <img src.bind="file | blobToUrl"><img>
      Last Modified: ${file.lastModifiedDate}
export class App {

Here's a live example: