Components Multi file upload

experimental

Use the multi file upload component to help users upload multiple files at the same time.

<div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds">

<h1 class="govuk-heading-xl">Upload files</h1>

<form action="/components/multi-file-upload/examples/default" method="post" enctype="multipart/form-data">

  <div class="moj-multi-file-upload">
    <div class="moj-multi-file__uploaded-files ">
      <h2 class="govuk-heading-m">Files added</h2>
      <div class="govuk-summary-list moj-multi-file-upload__list">

      </div>
    </div>

    <div class="moj-multi-file-upload__upload">

      <div class="govuk-form-group">
        <label class="govuk-label govuk-label--m" for="documents">
          Upload a file
        </label>

        <input class="govuk-file-upload moj-multi-file-upload__input" id="documents" name="documents" type="file" multiple="">
      </div>

      <button type="submit" class="govuk-button govuk-button--secondary moj-multi-file-upload__button" data-module="govuk-button">
        Upload file
      </button>

    </div>
  </div>

  <button type="submit" class="govuk-button" data-module="govuk-button">
    Continue
  </button>

</form>
</div>
</div> 
if (typeof MOJFrontend.MultiFileUpload !== 'undefined') {
  new MOJFrontend.MultiFileUpload({
    container: $('.moj-multi-file-upload'),
    uploadUrl: '/ajax-upload',
    deleteUrl: '/ajax-delete'
  });
}
{%- from "govuk/components/file-upload/macro.njk" import govukFileUpload -%}
{%- from "govuk/components/button/macro.njk" import govukButton -%}
{%- from "govuk/components/error-summary/macro.njk" import govukErrorSummary -%}
{%- from "moj/components/multi-file-upload/macro.njk" import mojMultiFileUpload -%}

<div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds">

{% if errorSummary.items.length %}
  {{ govukErrorSummary({
    titleText: 'There is a problem',
    errorList: errorSummary.items
  }) }}
{% endif %}

<h1 class="govuk-heading-xl">Upload files</h1>

<form action="/components/multi-file-upload/examples/default" method="post" enctype="multipart/form-data">
  {% set uploadHtml %}
    {{ govukFileUpload({
      id: "documents",
      name: "documents",
      classes: 'moj-multi-file-upload__input',
      label: {
        text: "Upload a file",
        classes: 'govuk-label--m'
      },
      attributes: { multiple: '' },
      errorMessage: errorMessage
    }) }}

    {{govukButton({
      text: 'Upload file',
      classes: 'govuk-button--secondary moj-multi-file-upload__button'
    })}}
  {% endset %}

  {{ mojMultiFileUpload({
    uploadedFiles: {
      heading: { text: 'Files added' },
      items: uploadedFiles
    },
    uploadHtml: uploadHtml
  }) }}

  {{govukButton({
    text: 'Continue'
  })}}
</form>
</div>
</div> 

You can configure this component using the Nunjucks macro arguments

When to use this component

The multi file upload component can be useful if you need to let users upload multiple files at once, on a regular basis. For example, in a caseworking system.

When not to use this component

Do not use this component if users only need to upload one file.

Uploading multiple files at the same time is more error prone than uploading files, one at a time. This is because users have to use a custom form control that may not be as easy to understand.

For this reason, do not use this component unless research shows that users need a faster way to upload files.

Read more about how to ask users to upload files.

How it works

The multi file upload consists of a dropzone and feedback area which starts off hidden.

Users can drag and drop files onto the dropzone or click the button and select files using the file picker.

Each selected file will start uploading immediately and appear as a row in the feedback area. Each file’s progress is indicated as a percentage.

When a file has been uploaded it will show as:

  • green, next to a tick icon, if it’s been uploaded successfully
  • red, next to a warning icon, if there’s been an error

Initialising the JavaScript

The multi file upload component uses JavaScript. To run it you must include the following script in your page:

if(typeof MOJFrontend.MultiFileUpload !== 'undefined') {
new MOJFrontend.MultiFileUpload({
container: $('.moj-multi-file-upload'),
uploadUrl: '/ajax-upload-url',
deleteUrl: '/ajax-delete-url'
});
}

When JavaScript is not available

When JavaScript is not available, users will be presented with a file upload component and upload button.

When the user selects the upload button, the page will refresh with the valid files being shown in the feedback area.

<div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds">

<h1 class="govuk-heading-xl">Upload files</h1>

<form action="" method="post" enctype="multipart/form-data">

  <div class="moj-multi-file-upload">
    <div class="moj-multi-file__uploaded-files moj-hidden">
      <h2 class="govuk-heading-m">Files added</h2>
      <div class="govuk-summary-list moj-multi-file-upload__list">

      </div>
    </div>

    <div class="moj-multi-file-upload__upload">

      <div class="govuk-form-group">
        <label class="govuk-label govuk-label--m" for="documents">
          Upload a file
        </label>

        <input class="govuk-file-upload moj-multi-file-upload__input" id="documents" name="documents" type="file" multiple="">
      </div>

      <button type="submit" class="govuk-button govuk-button--secondary moj-multi-file-upload__button" data-module="govuk-button">
        Upload file
      </button>

    </div>
  </div>

  <button type="submit" class="govuk-button" data-module="govuk-button">
    Continue
  </button>

</form>
</div>
</div> 
{%- from "govuk/components/file-upload/macro.njk" import govukFileUpload -%}
{%- from "govuk/components/button/macro.njk" import govukButton -%}
{%- from "govuk/components/error-summary/macro.njk" import govukErrorSummary -%}
{%- from "moj/components/multi-file-upload/macro.njk" import mojMultiFileUpload -%}

<div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds">

<h1 class="govuk-heading-xl">Upload files</h1>

<form action="" method="post" enctype="multipart/form-data">
  {% set uploadHtml %}
    {{ govukFileUpload({
      id: "documents",
      name: "documents",
      classes: 'moj-multi-file-upload__input',
      label: {
        text: "Upload a file",
        classes: 'govuk-label--m'
      },
      attributes: { multiple: '' }
    }) }}

    {{govukButton({
      text: 'Upload file',
      classes: 'govuk-button--secondary moj-multi-file-upload__button'
    })}}
  {% endset %}

  {{ mojMultiFileUpload({
    uploadedFiles: {
      heading: { text: 'Files added' },
      items: []
    },
    uploadHtml: uploadHtml
  }) }}

  {{govukButton({
    text: 'Continue'
  })}}
</form>
</div>
</div> 

You can configure this component using the Nunjucks macro arguments

When there are multiple files with errors, you must put:

<div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds">

<div class="govuk-error-summary" aria-labelledby="error-summary-title" role="alert" tabindex="-1">
  <h2 class="govuk-error-summary__title" id="error-summary-title">
    There is a problem
  </h2>
  <div class="govuk-error-summary__body">

    <ul class="govuk-list govuk-error-summary__list">

      <li>

        <a href="#documents">name-of-file-1.pdf must be a png or gif</a>

      </li>

      <li>

        <a href="#documents">name-of-file-2.pdf must be a png or gif</a>

      </li>

    </ul>
  </div>
</div>

<h1 class="govuk-heading-xl">Upload files</h1>

<form action="" method="post" enctype="multipart/form-data">

  <div class="moj-multi-file-upload">
    <div class="moj-multi-file__uploaded-files moj-hidden">
      <h2 class="govuk-heading-m">Files added</h2>
      <div class="govuk-summary-list moj-multi-file-upload__list">

      </div>
    </div>

    <div class="moj-multi-file-upload__upload">

      <div class="govuk-form-group govuk-form-group--error">
        <label class="govuk-label govuk-label--m" for="documents">
          Upload a file
        </label>

        <span id="documents-error" class="govuk-error-message">
          <span class="govuk-visually-hidden">Error:</span> name-of-file-1.pdf must be a png or gif<br>name-of-file-2.pdf must be a png or gif
        </span>

        <input class="govuk-file-upload moj-multi-file-upload__input govuk-file-upload--error" id="documents" name="documents" type="file" aria-describedby="documents-error" multiple="">
      </div>

      <button type="submit" class="govuk-button govuk-button--secondary moj-multi-file-upload__button" data-module="govuk-button">
        Upload file
      </button>

    </div>
  </div>

  <button type="submit" class="govuk-button" data-module="govuk-button">
    Continue
  </button>

</form>
</div>
</div> 
{%- from "govuk/components/file-upload/macro.njk" import govukFileUpload -%}
{%- from "govuk/components/button/macro.njk" import govukButton -%}
{%- from "govuk/components/error-summary/macro.njk" import govukErrorSummary -%}
{%- from "moj/components/multi-file-upload/macro.njk" import mojMultiFileUpload -%}

<div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds">

<div class="govuk-error-summary" aria-labelledby="error-summary-title" role="alert" tabindex="-1">
  <h2 class="govuk-error-summary__title" id="error-summary-title">
    There is a problem
  </h2>
  <div class="govuk-error-summary__body">

    <ul class="govuk-list govuk-error-summary__list">

      <li>

        <a href="#documents">name-of-file-1.pdf must be a png or gif</a>

      </li>

      <li>

        <a href="#documents">name-of-file-2.pdf must be a png or gif</a>

      </li>

    </ul>
  </div>
</div>

<h1 class="govuk-heading-xl">Upload files</h1>

<form action="" method="post" enctype="multipart/form-data">
  {% set uploadHtml %}
    {{ govukFileUpload({
      id: "documents",
      name: "documents",
      classes: 'moj-multi-file-upload__input',
      label: {
        text: "Upload a file",
        classes: 'govuk-label--m'
      },
      attributes: { multiple: '' },
      errorMessage: {
        html: 'name-of-file-1.pdf must be a png or gif<br>name-of-file-2.pdf must be a png or gif'
      }
    }) }}

    {{govukButton({
      text: 'Upload file',
      classes: 'govuk-button--secondary moj-multi-file-upload__button'
    })}}
  {% endset %}

  {{ mojMultiFileUpload({
    uploadedFiles: {
      heading: { text: 'Files added' },
      items: []
    },
    uploadHtml: uploadHtml
  }) }}

  {{govukButton({
    text: 'Continue'
  })}}
</form>
</div>
</div> 

You can configure this component using the Nunjucks macro arguments

If the form contains other questions and the user selects the upload button:

  • save their answers and present them back
  • if there are errors, show them in the error summary and next to the related fields

When the user selects the continue button, the entire form including selected files, will be saved and the user will be taken to the next page.

You can include a check screen at this point if you need to.

Error messages

Use the file upload error messages from the GOV.UK Design System.

Research on this component

This component is marked as experimental because it needs more research.

If you have used the multi file upload component, get in touch to share your research findings.

Contribute to this component

You can contribute to this component via the design system backlog

Get in touch

If you’ve got a question, idea or suggestion share it on the #moj-design-system-support channel on Slack or email the Design System team on design-system@digital.justice.gov.uk