2

I have a form. It works... but the user must wait for the large file to upload first or they won't be processed by the form. The upload form will change from the Upload button to the name of the file with a Remove button.

    $validators = [
      'file_validate_extensions' => ['zip'],
    ];

    $form['static_archive'] = [
      '#type' => 'managed_file',
      '#name' => 'static_archive',
      '#title' => t('Static archive'),
      '#size' => 200,
      '#description' => t('ZIP format only'),
      '#upload_validators' => $validators,
      '#upload_location' => 'private://imports/uploads/',
    ];

    ...
    other fields here
    ...

    $form['actions']['#type'] = 'actions';
    $form['actions']['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Import Archive'),
      '#button_type' => 'primary',
    ];

This form is outputted on a route like I want, file is processed, etc. The only catch is the user having to wait.

I'm hoping there is some JS method for disabling the Submit button while the file is uploading. Bonus if there's a way to show upload progress or has a message explaining why it's disabled. The file upload is not a required field, so when the uses the form and the file doesn't upload before they hit submit, it's lost in the wind and the user doesn't even get an error.

This isn't webforms, so this doesn't solve it. https://www.drupal.org/project/webform/issues/3010084

This isn't solve via this patch: https://www.drupal.org/project/drupal/issues/2869855

I also tried clientside_validation: https://www.drupal.org/project/clientside_validation b/c of this: How to prevent an Ajax form from submitting

But I am having no luck solving this. Hoping someone has ideas to share.

1 Answer 1

1

After spending half the day searching, I finally got a solution. I ended up using some of the code from the webform module to prevent the form from being submitted. Specifically, take a look at the webform.element.managed_file.js and the patch from https://www.drupal.org/files/issues/2018-10-31/3010084-17.patch

I created my prevent_submit.js file below with the following:

(function ($, Drupal, once) {
Drupal.behaviors.preventSubmitForm = {
  attach: function (context, drupalSettings) {

    // Add submit handler to file upload form.
    $(context).find('form')
      .once('webform-auto-file-upload')
      .on('submit', function (event) {
        var $form = $(this);
        if ($form.data('webform-auto-file-uploads') > 0 && blockSubmit($form)) {
          event.preventDefault();
          return false;
        }
        return true;
      });

    $(context).find('input[type="file"]').once('webform-auto-file-upload').on('change', function () {

      // Track file upload.
      $(this).data('msk-auto-file-upload', true);

      // Increment form file uploads.
      var $form = $(this.form);
      var fileUploads = ($form.data('webform-auto-file-uploads') || 0);
      $form.data('webform-auto-file-uploads', fileUploads + 1);
    });

    /**
     * Block form submit.
     *
     * @param {jQuery} form
     *   A form.
     *
     * @returns {boolean}
     *   TRUE if form submit should be blocked.
     */
    function blockSubmit(form) {
      if ($(form).data('webform-auto-file-uploads') < 0) {
        return false;
      }

      var message = Drupal.t('File upload in progress. Uploaded file may be lost.') +
        '\n' +
        Drupal.t('Do you want to continue?');
      return !window.confirm(message);
    }
 
  },
  detach: function detach(context, settings, trigger) {
    if (trigger === 'unload') {
      $(context).find('input[type="file"]').removeOnce('webform-auto-file-upload').each(function () {
        if ($(this).data('msk-auto-file-upload')) {
          // Remove file upload tracking.
          $(this).removeData('msk-auto-file-upload');

          // Decrease form file uploads.
          var $form = $(this.form);
          var fileUploads = ($form.data('webform-auto-file-uploads') || 0);
          $form.data('webform-auto-file-uploads', fileUploads - 1);
        }
      });
    }
  }
};
  }
)
(jQuery, Drupal, once);
1
  • This looks very clean. I gave you some props as a good response, but I no longer work on the site this issue originally was raised by, so can't test for sure. But I can see myself coming back to this answer in the future for various reasons.
    – eahonet
    Jun 1, 2022 at 15:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.