Two different action as per users’ preference, on the same data provided. For (dumb) example: User can choose to be greeted either in Spanish or in French.

<form id="greeting-form" method="get" action="">
  <input type="text" name="name" value="Sarbbottam">

  <input type="submit" id="hola-button" value="Hola" name="greeting">
  <input type="submit" id="bonjour-button" value="Bonjour" name="greeting">
</form>

User action vs Form data

Form data passed, to the form action, depends on the user interaction.

user action form data passed
clicks on Hola button name=Sarbbottam&greeting=Hola
clicks on Bonjour button name=Sarbbottam&greeting=Bonjour
tabs to the Hola button and presses enter in the physical keyboard name=Sarbbottam&greeting=Hola
tabs to the Bonjour button and presses enter in the physical keyboard name=Sarbbottam&greeting=Bonjour
while being in the name field (editable fields), presses enter in the physical keyboard or Go in the soft keyboard* name=Sarbbottam&greeting=Hola

</sup> *Pressing/tapping the enter/Go button, triggers the click event on first submit button (the submit button that appears first in the DOM).

Form action handler, can rely on the value of greeting parameter to take desired action.

if(greeting === 'Hola') {
  // Hola action
} else {
  // Bonjour action
}

Example - Two submit button

See the Pen greeting-no-js by Sarbbottam Bandyopadhyay (@sarbbottam) on CodePen.

Form action handler is relying on the value of the greeting parameter(name of the submit button) to greet the user.

What problem might arise?

So far so good, but if the form submit action is trapped click event of the submit buttons is trapped and the form is submitted via JavaScript, the greeting parameter will not be part of the form data.

However, if the form submit event is trapped and the form is submitted via JavaScript, the clicked button will be part of the serialized form data. Thanks to Adam Brunner for the pointer.

var holaButton = document.getElementById('hola-button');
var bonjourButton = document.getElementById('bonjour-button');
var greetingForm = document.getElementById('greeting-form');

var submitForm = function(e) {
  e.preventDefault();
  e.stopPropagation();
  // some action, firing beacon with the value of the submit button
  greetingForm.submit();
};

holaButton.addEventListener('click', submitForm, false);
bonjourButton.addEventListener('click', submitForm, false);

See the Pen greeting-js-buggy by Sarbbottam Bandyopadhyay (@sarbbottam) on CodePen.

Since the greeting parameter is not present the form action handler behavior is buggy.

Proposed solution

Instead of listening to submit button click, listening to form submit resolves the issue. Sweet and simple.

But the whole idea of the previously proposed solution was to detect which submit button was clicked.

The submit button clicked can be detected with document.activeElement.

var greetingForm = document.getElementById('greeting-form');

var submitForm = function(e) {
  e.preventDefault();
  e.stopPropagation();
  // which submit button is clicked
  var activeElement = document.activeElement;
  if(activeElement.type === 'submit' && activeElement.name !== '') {
    console.log(activeElement.value);
  }
  // some action, firing beacon with the value of the submit button
  greetingForm.submit();
};

greetingForm.addEventListener('submit', submitForm, false);

See the Pen greeting-js-proper by Sarbbottam Bandyopadhyay (@sarbbottam) on CodePen.

(Previously) Proposed solution (not optimal)

Using a hidden input to track the user action (the button clicked).

<input type="hidden" id="proxy-submit-button">

Before the form is submitted via JavaScript, the name and value of the proxy-submit-button is updated.

var holaButton = document.getElementById('hola-button');
var bonjourButton = document.getElementById('bonjour-button');
var proxySubmitButton = document.getElementById('proxy-submit-button');
var greetingForm = document.getElementById('greeting-form');

var submitForm = function(e) {
  e.preventDefault();
  e.stopPropagation();
  /* set the proxy button value */
  proxySubmitButton.value = this.value;
  /* set the proxy button name */
  proxySubmitButton.name = this.name;
  greetingForm.submit();
};

holaButton.addEventListener('click', submitForm, false);
bonjourButton.addEventListener('click', submitForm, false);

See the Pen greeting-js-proper by Sarbbottam Bandyopadhyay (@sarbbottam) on CodePen.

If for any reason JavaScript is not executed, the proxy-submit-button element will not be passed to the form action as it does not have any name and greeting parameter will always be passed to the form action.

If JavaScript is functional, then proxy-submit-button will be named as greeting and its value will be updated to the value of the submit button clicked*. Thus at a time only one parameter named greeting will be passed to the form action.

</sup> *Pressing/tapping the enter/Go button, triggers the click event on first submit button (the submit button that appears first in the DOM).

Wrap up

Technically, the proposed solution holds good for any number of submit buttons but more than two submit button might not be a desired user experience.

Thanks to Chris Coyier for the mention, Adam Brunner for the suggestion and internet for its feedback.


If you have enjoyed reading this post you can follow me on twitter @sarbbottam and learn about any new posts. Opinions expressed are solely my own and do not express the views or opinions of my employer.