Form submitted using submit() from a link cannot be caught by onsubmit handler
Asked Answered
G

3

7

Surprised, I am encountering this weird issue while submitting form from JS.

Issue:

Consider a simple form submitted using two ways from a submit button and an anchor link

<form method="POST" action="page.html" name="foobar" id="test">
  <input type="text" />
  <input type="submit" />
</form>

<a href="#" onclick="document.getElementById('test').submit();">click me</a>

Function catching the submit event

document.getElementById('test').onsubmit = function() {
   // Same result with 
   //     * document.foobar.onsubmit
   //     * document.forms['foobar'].onsubmit

   alert('foobar');
   return false;
}

Now, when the form is submitted from clicking the submit button I get the alert, but not when clicking the link. Why is this doing so?

Fiddle Showing the Issue

Guanine answered 10/10, 2012 at 12:28 Comment(2)
Replace onclick="document.getElementById('test').submit();" with onclick="document.getElementById('test').onsubmit();"Coats
@javascriptisfuture—that doesn't submit the form, it just calls the onsubmit listener.Madore
M
13

To provide a reasonably definitive answer, the HTML Form Submission Algorithm item 5 states that a form only dispatches a submit event if it was not submitted by calling the submit method (which means it only dispatches a submit event if submitted by a button or other implicit method, e.g. pressing enter while focus is on an input type text element).

If no submit event is dispatched, then the submit handler won't be called.

That is different to the DOM 2 HTML specification, which said that the submit method should do what the submit button does.

So if you want to use script to submit a form, you should manually call the submit listener. If the listener was added using addEventListener, then you'll need to remember that and to call it since you can't discover it by inspecting the form (as suggested below).

If the listener is set inline, or added to the DOM onsubmit property, you can do something like:

<form onsubmit="return validate(this);" ...>
  ...
</form>
<button onclick="doSubmit()">submit form</button>

<script>
function doSubmit() {
  var form = document.forms[0];

  if (form.onsubmit) {
    var result = form.onsubmit.call(form);
  }

  if (result !== false) {
    form.submit();
  }
}
</script>

Life is tougher if you need to pass parameters or do other things.

Madore answered 10/10, 2012 at 13:42 Comment(0)
M
1

Thats how form.submit behaves;

The form's onsubmit event handler (for example, onsubmit="return false;") will not be triggered when invoking this method from Gecko-based applications. In general, it is not guaranteed to be invoked by HTML user agents

Make onsubmit call a function and simply call that onclick as well.

Mcginn answered 10/10, 2012 at 12:34 Comment(6)
I came to know it does not get invoked. But, do you know any reason why this happens? Or, is it that browsers are made that way?Guanine
The event is designed to fire only when the user submits the form, not jsMcginn
But isn't user also submitting the form by click on an anchor link and calling methods to submit the forms??Guanine
No, they are clicking an anchor link that happens to call the .submit methodMcginn
@AlexK—The W3C HTML spec says that the submit method "Submits the form. It performs the same action as a submit button.", so it seems reasonable to me that it would also cause the form's submit listener to be called, if not dispatch a submit event. However, that isn't what some (most?) browsers do.Madore
@AlexK—note that in the HTML "living standard", section 4.10.22.3 Form submission algorithm, if a form is submitted by calling its submit method, the form is not validated, nor is a submit event dispatched so the submit handler is never called.Madore
F
1

Instead of programatically submitting the form using the forms submit() function, you could manually construct and dispatch a submit event.

const buttonEl = document.getElementById('your-button');
const formEl = document.getElementById('your-form');

buttonEl.addEventListener('click', () => {
   const submitEvent = new Event('submit');
   formEl.dispatchEvent(submitEvent);
});

This means any other listener on the form submit event will fire:

formEl.addEventListener('submit', (submitEvent) => {
    console.log('The form submitted!');
});
Feme answered 20/10, 2022 at 22:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.