Components Multi file upload

Last updated: 25 January 2024

<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>

{%- 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>
new MOJFrontend.MultiFileUpload({
  container: document.querySelector(".moj-multi-file-upload"),
  uploadUrl: "/ajax-upload",
  deleteUrl: "/ajax-delete",
});

To use the component in your design, add the MoJ Figma Kit to your Figma libraries and find the component using the Assets tab.

View component in MoJ Figma Kit

When to use

Use the multi file upload component to help users upload multiple files at the same time, on a regular basis. For example, in a caseworking system.

When not to use

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.

How to use

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: document.querySelector('.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>

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>

            <p 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

            </p>

            <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>

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.