What's Standard Behavior When ≪Button≫ Element Is Clicked? Will It Submit the Form

What's standard behavior when <button> element is clicked? Will it submit the form?

If the button is within a form, the default behavior is submit.

If the button is not within a form, it will do nothing.

BUT BE AWARE!

Always specify the type attribute for
the button. The default type for
Internet Explorer is "button", while
in other browsers (and in the W3C
specification) it is "submit".

Taken from http://www.w3schools.com/tags/tag_button.asp

How is the default submit button on an HTML form determined?

If you submit the form via JavaScript (i.e., formElement.submit() or anything equivalent), then none of the submit buttons are considered successful and none of their values are included in the submitted data. (Note that if you submit the form by using submitElement.click() then the submit that you had a reference to is considered active; this doesn't really fall under the remit of your question since here the submit button is unambiguous but I thought I'd include it for people who read the first part and wonder how to make a submit button successful via JavaScript form submission. Of course, the form's onsubmit handlers will still fire this way whereas they wouldn't via form.submit() so that's another kettle of fish...)

If the form is submitted by hitting Enter while in a non-textarea field, then it's actually down to the user agent to decide what it wants here. The specifications don't say anything about submitting a form using the Enter key while in a text entry field (if you tab to a button and activate it using space or whatever, then there's no problem as that specific submit button is unambiguously used). All it says is that a form must be submitted when a submit button is activated. It's not even a requirement that hitting Enter in e.g. a text input will submit the form.

I believe that Internet Explorer chooses the submit button that appears first in the source; I have a feeling that Firefox and Opera choose the button with the lowest tabindex, falling back to the first defined if nothing else is defined. There's also some complications regarding whether the submits have a non-default value attribute IIRC.

The point to take away is that there is no defined standard for what happens here and it's entirely at the whim of the browser - so as far as possible in whatever you're doing, try to avoid relying on any particular behaviour. If you really must know, you can probably find out the behaviour of the various browser versions, but when I investigated this a while back there were some quite convoluted conditions (which of course are subject to change with new browser versions) and I'd advise you to avoid it if possible!

Form is submitted when I click on the button in form. How to avoid this?

From the fine HTML5 specification:

A button element with no type attribute specified represents the same thing as a button element with its type attribute set to "submit".

And a <button type="submit"> submits the form rather than behaving like a simple <button type="button"> push-button.

The HTML4 spec says the same thing:

type = submit|button|reset [CI]

This attribute declares the type of the button. Possible values:

  • submit: Creates a submit button. This is the default value.
  • reset: Creates a reset button.
  • button: Creates a push button.

So your <button> elements:

<button class="btn">Button_1</button>
<button class="btn">Button_2</button>

are the same as these (in compliant browsers):

<button type="submit" class="btn">Button_1</button>
<button type="submit" class="btn">Button_2</button>

and any time you hit one of those buttons you'll submit your form.

The solution is to use plain buttons:

<button type="button" class="btn">Button_1</button>
<button type="button" class="btn">Button_2</button>

Some versions of IE default to type="button" despite what the standard says. You should always specify the type attribute when using a <button> just to be sure that you will get the behavior you're expecting.

Why does calling submit on a form and click on a submit button produce different GET parameters?

This behavior is specified in the HTML standard:

The submit() method, when invoked, must submit the form element from the form element itself, with the submitted from submit() method flag set.

Where submission carries out the many steps described here:

When a form element form is submitted from an element submitter (typically a button), optionally with a submitted from submit() method flag set, the user agent must run the following steps:

...


  1. Let submitterButton be null if submitter is form. Otherwise, let submitterButton be submitter.

...


  1. Let entry list be the result of constructing the entry list with form, submitter, and encoding.

Where the entry list eventually results in a string like ?password_new=hacked&password_conf=hacked.

If you submit the form by pressing the button (either manually or programatically), submitter is set to the button, so the entry list includes the button.

If you submit the form by using .submit(), submitter is set to the form, so submitterButton is set to null, so the entry list does not include it.

The construction of the entry list skips buttons which are not submitter:

For each element field in controls, in tree order:

If any of the following is true:

The field element is a button but it is not submitter.

Then continue.

Understanding HTML Form Element behavior

TL;DR; Showing the message and redirecting later provides the document location to stay on the current page. You can't submit a form and stay on the current page. Use AJAX aka XMLHttpRequest to send the data to your server instead of submitting a form.

How HTMLFormElement works

On early days, before JavaScript existed, form element was purposed to send data from a page to a server, then the server handled the data, and responded with a new page, which was loaded by the browser. Even today, browsers are doing exactly this same when a form is submitted.

The standard says:

"The form element represents a hyperlink that can be manipulated through a collection of form-associated elements" (emphasis mine).

Now, if you're not interested in a deeper explanation of how the form submission works under the hood, you can scroll down to the All this in practice chapter.

But what actually happens when a submit button is clicked? The standard defines a Form submission algorithm, which is very deeply detailed, and is a bit hard to follow. Here are the strongly simplified main steps:

  1. Browser checks whether the form can be submitted (document fully active, sandboxing etc.), failing the check cancels the algorithm
  2. Validation defined by the elements' attributes is executed, if validation fails the algorithm is cancelled
  3. The attached submit event(s) are executed (attached event(s) can fire only once)
  4. If any of the submit handlers called event.preventDefault the algorithm is cancelled
  5. The encoding of the form is set
  6. An entry list of the form control elements is created
  7. Various attributes of the form are parsed (ex. action defaults to the URL of the form's document if the attribute is not set)
  8. The internal sending method is selected based on method attribute of the form (defaults to GET) and the schema of the URL in action attribute
  9. A navigation plan is created (a task) and send to the event queue (includes the deformed form data)
  10. The task in the event queue is executed, and navigation to a new page takes place

In the real algorithm, a lot more of actions are executed, ex. step 1 is executed between many of the steps, and the algorithm prevents concurrent submissions. Also, the described algorithm stands only when an actual submit button is activated. If the submission is called via JS by form.submit method, steps 2 - 4 are jumped over.

The above algorithm explains how JS form validation in submit event handler can cancel the submission (#4). The unload document process (#10) explains how the timeout is broken when a new page is about to load (all the pending timers and events are aborted). But, any of these doesn't actually explain, how location.href in a submit event handler is ignored without the timeout.

The answer to this question is hidden in the definition of the form: It "represents a hyperlink". Activating a hyperlink sets a specific internal navigation event, and an internal "ongoing-navigation" flag. Any later activation of any hyperlink checks that flag, and is cancelled if the flag was set. Setting location.href is not actually a hyperlink, but it uses the same navigation mechanisms, hence it's also cancelled, if a pending navigation is detected. It's notable, that calling event.preventDefault in a submit handler unsets the "ongoing-navigation" flag immediately, which makes setting location.href to work again later in the handler.

(The navigation behavior described above is heavily simplified. To fully understand how the browser navigation works, provides deep knowledge of the event queues and navigation process, which are described in the standard (details being even partially implementation-dependent), but these are not the objective of this answer.)

All this in practice

As the most of the previously described actions of HTML Form are executed under the hood, how can this all be applied in the point of the view of a programmer? Let's make a synthesis (without specific rationales).

  • <form> is a link which can send more information to the server than a regular link like <a>
  • action attribute of a form is roughly equal to href attribute of a regular link
  • Submitting a form always loads a new page, this is the default action of the submission
  • Any attempt to navigate to another page (including clicking links or submitting other forms, or setting location.href in JS) is prevented while a submit event is pending
  • Programmer can interfere form submission by setting a submit event listener to the form
  • If attribute-based form validation fails, attached submit event handler(s) is/are not executed
  • A submit event handler can modify the current page and the data to submit, and it also can cancel the form submission
  • Nevertheless what is done in a submit event handler, the form is submitted when the handler execution is finished, unless the handler cancels the default action of the submit event

What triggers a form submission then? There are multiple ways to start a form submission. All the elements below are so called submitter elements, those have "submit the form" as their default action:

  1. <input type="submit" value="Submit">
  2. <input type="image" alt="Submit">
  3. <button type="submit">Submit</button>
  4. <button>Submit</button>
  5. Hitting ENTER on active <input type="date/number/password/search/tel/text/time/url/week">
  6. Calling form.submit method in JS

Notice the typeless <button> element, it's also a submit button by default, when placed inside a form.

Preventing the default action of an event

Some events have a default action, which is executed after the event handler function has finished. For example, the default action of submit event is to submit the form triggered the event. You can prevent the default action to be executed in the event handler by calling preventDefault method of the event object:

event.preventDefault();

event is either the object passed in the arguments of the handler, or the global event object.

Returning false from an event handler function doesn't prevent the form submission. This works with inline listeners only, when return false; is written in an onsubmit attribute.

The first three elements in the submitter element list above are "stronger" than the other elements. If you've attached a click listener to an input type of submit/image or a button type of submit, preventing the default action of the (click) event doesn't prevent the form submission. Other elements can do that also within a click listener. To prevent the submission in all cases, you've to listen to submit event on the form instead of clicks on the submitter elements.

And again: form.submit method called in any script, will jump over all form validations and won't fire any submit events, it can't be cancelled via JS. It's notable, that this stands for the native submit method only, ex. jQuery's .submit isn't native, and it calls the attached submit handlers.

Send data and stay on the current page

To send data and still stay on the current page can be achieved only by not submitting the form. There are multiple ways to prevent the submission. The simplest way is to not include a form in the markup at all, that makes a lot of extra work with data handling in JS, though. The best way is to prevent the default action of the submit event, any other way with a form would cause extra work, for example, triggering JS without a submitter element still provides detecting submissions made by #5 in the submitter elements list.

As the data won't go to a server without submitting, you need to send the data with JS. The technique to use is called AJAX (Asynchronous Javascript And Xml).

Here's a simple vanilla JS code example of sending data to the server, and staying on the current page. The code utilizes XMLHttpRequest object. Typically the code is placed in a submit event handler of a form, as it is in the example below. You can make a request anywhere in the scripts on a page, and if a submit event is not involved, preventing the default action is not needed.

form.addEventListener('submit', e => {
const xhr = new XMLHttpRequest();
const data = new FormData(form);

e.preventDefault();

xhr.open('POST', 'action_URL');
xhr.addEventListener('load', e => {
if (xhr.status === 200) {
// The request was successful
console.log(xhr.responseText);
} else {
// The request failed
console.log(xhr.status);
}
});
xhr.send(data);
});

The analogy to a form is scattered allover the code:

  • control element values are included in data (form being a reference to an existing form element)
  • method attribute is the first argument of xhr.open
  • action attribute is the second argument of xhr.open
  • enctype attribute is created by FormData constructor (defaults to "multipart/form-data")

The difference between AJAX and form submission is, that when getting a response for an AJAX call from the server, the JavaScript execution continues in the load handler of xhr instead of browser loading a new page when submitting a form. In that load handler you can do what ever you need with the data server sent as the response, or just redirect (also succesfully with a timeout). It's also possible to leave the load handler out of the code, when you don't need a notify of the request success/failure or any response data.

In modern browsers you can also use Fetch API to make an AJAX request. Also, most of the commonly used frameworks (if not all) and many libraries (like jQuery), have their own (more or less simplified) implementations for various AJAX-based tasks.

Remarks

Due to the order of the tasks executed in the internal submit algorithm, the validation attributes are handled before calling the submit event handler(s). If any of the validations fails, the algorithm is cancelled. This means, that when the form validation fails, also the submit event handler(s) are not executed.

Validation based on the validation attributes is executed only after activating a submitter element, validation attributes are not affecting to an object created by FormData constructor, which can be created at any time, a submit event is not necessarily needed.

The target attribute of the form is ignored when creating a FormData object. An AJAX call always targets to the current page, it can't be redirected to another document.

It's not mandatory to send a FormData object, you can send any data you need, but it has to be formatted according to the method of the request.

Keep button from submitting form Javascript

Since you're not using a type="submit" the only reason your form would submit anything is because you're literally calling the submit() method when the button is clicked. (well, sort of. It's actually form.submit() - the method you created is window.submit()).

By default, an input of type="button" will not do a form submission unless you literally call form.submit()

Is there a standard resource for the default action of HTML elements?

The relevant documents are DOM3 Events and the HTML 5 specification.

They might not have all information you need, but should. So if you find them lacking, please request those behaviors to be specified.

2 buttons on form only 1 with submit type but both triggers submit event

set the type attribute to "button" or manually cancel the event

<button type='button' class='add'>add</button>

-or-

$('button.add').click(function(e){
e.preventDefault(); // cancel default behavior
// my add logic
});


Related Topics



Leave a reply



Submit