3

I have a form that generates some custom financial reports (can't use Views). It has some typical form elements, a table of results, and three submit buttons: Submit, Reset, and Download.

Submit and Reset do what you think. Download triggers a submit handler that builds a CSV from the $form['table'] in the handler (which is what the user has generated, and prevents another complicated database query + computations and another route to essentially do the same work), and then spits it out with a $form_state->setResponse($response). This works great.

I discovered an interesting edge case, though, during testing.

core/misc/form.es6.js has a section of code in it (lines 117-134 in Drupal 8.8.5):

Drupal.behaviors.formSingleSubmit = {
  attach() {
    function onFormSubmit(e) {
      const $form = $(e.currentTarget);
      const formValues = $form.serialize();
      const previousValues = $form.attr('data-drupal-form-submit-last');
      if (previousValues === formValues) {
        e.preventDefault();
      } else {
        $form.attr('data-drupal-form-submit-last', formValues);
      }
    }

    $('body')
      .once('form-single-submit')
      .on('submit.singleSubmit', 'form:not([method~="GET"])', onFormSubmit);
  },
};

This prevents a form from being submitted more than once if it hasn't changed. However, since my Download button is a submit handler, the above code runs, which then prevents the Reset button from working unless another form element has been changed.

My current workaround is a bit of a sledgehammer:

Drupal.behaviors.sledgehammer = {
  attach: function (context, settings) {
    $('form.my-form', context).on('submit', function (e) {
      var $form = $(e.currentTarget);
      $form.removeAttr('data-drupal-form-submit-last');
    });
  }
};

As far as I can tell this works, but I have BigPipe turned on and am going to AJAX up the form a bit, so I am worried that this may be fragile.

Is there an JS API way to disable the single-submit behavior, or is a workaround the only solution?

1 Answer 1

3

If you haven't already, try using button rather than submit type.

'#type' => 'button',

When the button is pressed, the form will be submitted to Drupal, where it is validated and rebuilt. The submit handler is not invoked.

Perhaps this will prevent that formSingleSubmit behavior from running???


If the above doesn't work, since all the formSingleSumit behaviour does is prevent form from being submitted if it hasn't changed and nothing else. Therefore, you don't need this behaviour and since Drupal is global, you could just do in custom.js:

delete Drupal.behaviors.formSingleSubmit;

OR set it/override it to empty

Drupal.behaviors.formSingleSubmit = {};

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.