5.14.4

Integrating with Existing HTML Forms

Overview

Say you have an existing HTML form. Say you want to simply allow your users to send files along with the form data. Fine Uploader form support will allow you to do this quite easily. A number of conventions are in place to allow incredibly easy integration of Fine Uploader into your existing form. If you follow all of these conventions, and only require the most basic features, you can initialize and attach Fine Uploader to your form with only one simple line of JavaScript! But don't worry, any of these conventions can be overridden via the form option. Fine Uploader will even respect any HTML5 validation attributes set on your form elements. Furthermore, you can include a traditional submit button in your form, and Fine Uploader will intercept this and upload all submitted files with the associated form data for you.

Features

Convention over configuration

A set of conventions are in place that allow you to simply include a form in your document and allow Fine Uploader to discover it and send all form data along with each upload request without explicitly setting any form-related configuration options. This can allow you to focus more on your form, and less on JavaScript. By default, Fine Uploader will:

  • Find your form automatically if it has an id attribute with a value of "qq-form". Once it finds your form, all file upload requests will include any data associated with that form, automatically!
  • Ensure any HTML5 validation attributes on your form elements are respected. If any form values are invalid, the user will be notified and the uploads will not occur.
  • Set the request.endpoint option to the value of your form's action attribute. This means that you don't even need to provide a request.endpoint configuration value when creating your Fine Uploader instance.
  • Intercept any attempt to submit your form and instead upload all user-selected files (along with associated form data).
  • Set Fine Uploader to "manual" upload mode. This means that uploads will not occur until you (or your user) indicate that they are done filling out the form and choosing files. You can allow your user to "submit" the form and trigger all files to be uploaded by simply providing a submit button in your form.

If you don't want to rely on some of these default behaviors, you can override them. See the form option for details. Note that, as of Fine Uploader 5.3, you can also attach a form to Fine Uploader at any time using the new setForm API method!

Validation

Fine Uploader will respect any validation attributes on your form elements, provided the current browser supports the HTML5 Constraints Validation API. When an attempt is made to submit the associated form, if there are validation issues, Fine Uploader will prevent the files from being uploaded until the issues are resolved by the user. Furthermore, the specific issues will be highlighted in the UI.

Note:

Validation will only occur if you attempt to submit your form via a submit button, or by triggering the form's submit function, or by triggering a submit event on the form. If you trigger an upload via the uploadStoredFiles API method, the form will not be validated.

Submit support

Submit attempts that target your attached form will be intercepted by default. When Fine Uploader intercepts a submit attempt, it will first attempt to validate the form. If the form is valid, or if the current browser does not have native support for form validation, the user-selected files will be uploaded along with the form data. Fine Uploader will intercept submit attempts triggered by a form submit button, invocation of the form element's submit function, or via a submit event.

You can prevent Fine Uploader from intercepting submit events by adjusting the form.interceptSubmit option.

When are all uploads done?

A new callback/event has been added: onAllComplete. This will be triggered when all selected files have been uploaded (successfully or not). Fine Uploader will pass an array of all successfully uploaded file IDs, and an array of all failed file IDs. If you need to notify your server when all associated files are done, you can safely implement this logic in a contributed onAllComplete event handler.

Cross-browser

The form support feature, like most other Fine Uploader features, works in all supported browsers.

Simple example

The simplest use-case results in a very simple example, with only one line of JavaScript! Here is a complete HTML file that integrates Fine Uploader into an existing form:

Note

There are many ways to load Fine Uploader into your project. The code below creates a global qq variable, but there are other, better options. Please see modules feature page for more details.

<html>
    <head>
        <script src="fine-uploader.js"></script>
        <link href="fine-uploader-new.css">
        <script type="text/template" id="qq-template">
            <div class="qq-uploader-selector qq-uploader" qq-drop-area-text="Drop files here">
                <div class="qq-total-progress-bar-container-selector qq-total-progress-bar-container">
                    <div role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" class="qq-total-progress-bar-selector qq-progress-bar qq-total-progress-bar"></div>
                </div>
                <div class="qq-upload-drop-area-selector qq-upload-drop-area" qq-hide-dropzone>
                    <span class="qq-upload-drop-area-text-selector"></span>
                </div>
                <div class="qq-upload-button-selector qq-upload-button">
                    <div>Upload a file</div>
                </div>
                <span class="qq-drop-processing-selector qq-drop-processing">
                    <span>Processing dropped files...</span>
                    <span class="qq-drop-processing-spinner-selector qq-drop-processing-spinner"></span>
                </span>
                <ul class="qq-upload-list-selector qq-upload-list" aria-live="polite" aria-relevant="additions removals">
                    <li>
                        <div class="qq-progress-bar-container-selector">
                            <div role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" class="qq-progress-bar-selector qq-progress-bar"></div>
                        </div>
                        <span class="qq-upload-spinner-selector qq-upload-spinner"></span>
                        <img class="qq-thumbnail-selector" qq-max-size="100" qq-server-scale>
                        <span class="qq-upload-file-selector qq-upload-file"></span>
                        <span class="qq-edit-filename-icon-selector qq-edit-filename-icon" aria-label="Edit filename"></span>
                        <input class="qq-edit-filename-selector qq-edit-filename" tabindex="0" type="text">
                        <span class="qq-upload-size-selector qq-upload-size"></span>
                        <button type="button" class="qq-btn qq-upload-cancel-selector qq-upload-cancel">Cancel</button>
                        <button type="button" class="qq-btn qq-upload-retry-selector qq-upload-retry">Retry</button>
                        <button type="button" class="qq-btn qq-upload-delete-selector qq-upload-delete">Delete</button>
                        <span role="status" class="qq-upload-status-text-selector qq-upload-status-text"></span>
                    </li>
                </ul>

                <dialog class="qq-alert-dialog-selector">
                    <div class="qq-dialog-message-selector"></div>
                    <div class="qq-dialog-buttons">
                        <button type="button" class="qq-cancel-button-selector">Close</button>
                    </div>
                </dialog>

                <dialog class="qq-confirm-dialog-selector">
                    <div class="qq-dialog-message-selector"></div>
                    <div class="qq-dialog-buttons">
                        <button type="button" class="qq-cancel-button-selector">No</button>
                        <button type="button" class="qq-ok-button-selector">Yes</button>
                    </div>
                </dialog>

                <dialog class="qq-prompt-dialog-selector">
                    <div class="qq-dialog-message-selector"></div>
                    <input type="text">
                    <div class="qq-dialog-buttons">
                        <button type="button" class="qq-cancel-button-selector">Cancel</button>
                        <button type="button" class="qq-ok-button-selector">Ok</button>
                    </div>
                </dialog>
            </div>
        </script>
    </head>

    <body>
        <form action="server/uploads.php" id="qq-form">
            <label>Enter your name</label>
            <input type="text" name="user_name" required>
            <label>Enter your email</label>
            <input type="email" name="user_email" required>
            <input type="submit" value="Done">
        </form>

        <div id="my-uploader"></div>

        <script>
            var uploader = new qq.FineUploader({
                element: document.getElementById('my-uploader')
            });
        </script>
    </body>
</html>