web-dev-qa-db-fra.com

jQuery: comment obtenir quel bouton a été cliqué lors de la soumission du formulaire?

J'ai un événement .submit() configuré pour la soumission du formulaire. J'ai également plusieurs formulaires sur la page, mais juste un ici pour cet exemple. Je voudrais savoir quel bouton de soumission a été cliqué sans appliquer un événement .click() à chacun.

Voici la configuration:

<html>
<head>
  <title>jQuery research: forms</title>
  <script type='text/javascript' src='../jquery-1.5.2.min.js'></script>
  <script type='text/javascript' language='javascript'>
      $(document).ready(function(){
          $('form[name="testform"]').submit( function(event){ process_form_submission(event); } );
      });
      function process_form_submission( event ) {
          event.preventDefault();
          //var target = $(event.target);
          var me = event.currentTarget;
          var data = me.data.value;
          var which_button = '?';       // <-- this is what I want to know
          alert( 'data: ' + data + ', button: ' + which_button );
      }
  </script>
</head>
<body>
<h2>Here's my form:</h2>
<form action='nothing' method='post' name='testform'>
  <input type='hidden' name='data' value='blahdatayadda' />
  <input type='submit' name='name1' value='value1' />
  <input type='submit' name='name2' value='value2' />
</form>
</body>
</html>

Exemple live sur jsfiddle

Outre l'application d'un événement .click () sur chaque bouton, existe-t-il un moyen de déterminer quel bouton d'envoi a été cliqué?

191
hawkexp

J'ai posé cette même question: Comment puis-je obtenir le bouton qui a provoqué la soumission de l'événement de soumission de formulaire?

J'ai fini par proposer cette solution et cela a très bien fonctionné:

$(document).ready(function() {
    $("form").submit(function() { 
        var val = $("input[type=submit][clicked=true]").val();
        // DO WORK
    });
    $("form input[type=submit]").click(function() {
        $("input[type=submit]", $(this).parents("form")).removeAttr("clicked");
        $(this).attr("clicked", "true");
    });
});

Dans le cas où vous avez plusieurs formulaires, vous devrez peut-être modifier un peu cela, mais cela devrait quand même s'appliquer

212
hunter

J'ai trouvé que cela fonctionnait.

$(document).ready(function() {
    $( "form" ).submit(function () {
        // Get the submit button element
        var btn = $(this).find("input[type=submit]:focus" );
    });
}
79
Stan

Cela fonctionne pour moi:

$("form").submit(function() {
   // Print the value of the button that was clicked
   console.log($(document.activeElement).val());
}
56
seddonym

Lorsque le formulaire est soumis: 

  • document.activeElement vous donnera le bouton d'envoi sur lequel vous avez cliqué.

  • document.activeElement.getAttribute('value') vous donnera la valeur de ce bouton.

37
Nick F

Voici l'approche qui semble plus propre pour mes besoins.

Tout d'abord, pour toutes les formes:

$('form').click(function(event) {
  $(this).data('clicked',$(event.target))
});

Lorsque cet événement click est déclenché pour un formulaire, il enregistre simplement la cible d'origine (disponible dans l'objet événement) à laquelle accéder ultérieurement. C'est un trait assez large, car il se déclenchera pour n'importe quel clic n'importe où sur le formulaire. Les commentaires d'optimisation sont les bienvenus, mais je suppose que cela ne posera jamais de problème notable.

Ensuite, dans $ ('formulaire'). Submit (), vous pouvez demander ce qui a été cliqué en dernier, avec quelque chose comme

if ($(this).data('clicked').is('[name=no_ajax]')) xhr.abort();
27
Jonathan Camenisch

Wow, certaines solutions peuvent se compliquer! Si cela ne vous dérange pas d'utiliser un simple global, profitez simplement du fait que l'événement de clic du bouton d'entrée est déclenché en premier. On pourrait filtrer davantage le sélecteur $ ('input') pour l'un des nombreux formulaires en utilisant $ ('# myForm input').

    $(document).ready(function(){
      var clkBtn = "";
      $('input[type="submit"]').click(function(evt) {
        clkBtn = evt.target.id;
      });

      $("#myForm").submit(function(evt) {
        var btnID = clkBtn;
        alert("form submitted; button id=" + btnID);
      });
    });
10
lawnbowler

J'ai trouvé la meilleure solution est

$(document.activeElement).attr('id')

Cela fonctionne non seulement sur les entrées, mais également sur les balises de bouton . En outre, il obtient l'identifiant du bouton.

7
Thomas Williams

Une autre solution possible consiste à ajouter un champ caché dans votre formulaire:

<input type="hidden" id="btaction"/>

Ensuite, dans la fonction Ready, ajoutez des fonctions pour enregistrer la touche sur laquelle vous avez appuyé:

$('form#myForm #btnSubmit').click(function() {
    $('form#myForm #btaction').val(0);
});

$('form#myForm #btnSubmitAndSend').click(function() {
    $('form#myForm #btaction').val(1);
});

$('form#myForm #btnDelete').click(function() {
    $('form#myForm #btaction').val(2);
});

Maintenant, dans le gestionnaire de soumission de formulaire, lisez la variable masquée et décidez en fonction:

var act = $('form#myForm #btaction').val();
6
wmac

S'appuyant sur ce que Stan et yann-h ont fait, mais celui-ci affiche par défaut le premier bouton. La beauté de cette approche globale réside dans le fait qu’elle saisit à la fois le clic et la touche entrée (même si le focus n’est pas sur le bouton. Si vous devez autoriser la saisie dans le formulaire, répondez-y simplement lorsqu'un bouton est activé ( c'est-à-dire la réponse de Stan.) Dans mon cas, je souhaitais autoriser enter à soumettre le formulaire même si le focus actuel de l'utilisateur était sur la zone de texte.

J'utilisais aussi un attribut «nom» plutôt que «identifiant», mais c'est la même approche.

var pressedButtonName =
     typeof $(":input[type=submit]:focus")[0] === "undefined" ?
     $(":input[type=submit]:first")[0].name :
     $(":input[type=submit]:focus")[0].name;
6
andrewmo

Si vous ne voulez pas ajouter d'événement .click à votre système, vous pouvez gérer tous les clics (envois) dans une seule fonction:

$(document).ready(function(){
  $('input[type="submit"]').click( function(event){ process_form_submission(event); } );
});

function process_form_submission( event ) {
  event.preventDefault();
  //var target = $(event.target);
  var input = $(event.currentTarget);
  var which_button = event.currentTarget.value;
  var data = input.parents("form")[0].data.value;
//  var which_button = '?';       // <-- this is what I want to know
  alert( 'data: ' + data + ', button: ' + which_button );
}
4
jcane86

Celui-ci a fonctionné pour moi

$('#Form').submit(function(){
var btn= $(this).find("input[type=submit]:focus").val();
alert('you have clicked '+ btn);

}
4
Saheb Mondal

Pour moi, les meilleures solutions étaient les suivantes:

$(form).submit(function(e){

   // Get the button that was clicked       
   var submit = $(this.id).context.activeElement;

   // You can get its name like this
   alert(submit.name)

   // You can get its attributes like this too
   alert($(submit).attr('class'))

});
3
Jeramiah Harland

En travaillant avec cette excellente réponse , vous pouvez vérifier l’élément actif (le bouton), ajouter une entrée masquée au formulaire et éventuellement le supprimer à la fin du gestionnaire d'envoi.

$('form.form-js').submit(function(event){
    var frm = $(this);
    var btn = $(document.activeElement);
    if(
        btn.length &&
        frm.has(btn) &&
        btn.is('button[type="submit"], input[type="submit"], input[type="image"]') &&
        btn.is('[name]')
    ){
        frm.append('<input type="hidden" id="form-js-temp" name="' + btn.attr('name') + '" value="' + btn.val() + '">');
    }

    // Handle the form submit here

    $('#form-js-temp').remove();
});

Note latérale: J'ajoute personnellement la classe form-js à tous les formulaires soumis via JavaScript. 

3
rybo111
$("form input[type=submit]").click(function() {
    $("<input />")
        .attr('type', 'hidden')
        .attr('name', $(this).attr('name'))
        .attr('value', $(this).attr('value'))
    .appendTo(this)
});

ajouter un champ caché

3
anydasa

Comme je ne peux pas commenter la réponse acceptée, j'apporte ici une version modifiée qui devrait prendre en compte les éléments extérieurs au formulaire (par exemple, attachés au formulaire à l'aide de l'attribut form). Ceci est pour le navigateur moderne: http://caniuse.com/#feat=form-attribute . closest('form') est utilisé comme solution de secours pour l'attribut form non pris en charge

$(document).on('click', '[type=submit]', function() {
    var form = $(this).prop('form') || $(this).closest('form')[0];
    $(form.elements).filter('[type=submit]').removeAttr('clicked')
    $(this).attr('clicked', true);
});

$('form').on('submit', function() {
    var submitter = $(this.elements).filter('[clicked]');
})
2
user3074069

C’est la solution que j’utilise et qui fonctionne très bien:

// prevent enter key on some elements to prevent to submit the form
function stopRKey(evt) {
  evt = (evt) ? evt : ((event) ? event : null);
  var node = (evt.target) ? evt.target : ((evt.srcElement) ? evt.srcElement : null);
  var alloved_enter_on_type = ['textarea'];
  if ((evt.keyCode == 13) && ((node.id == "") || ($.inArray(node.type, alloved_enter_on_type) < 0))) {
    return false;
  }
}

$(document).ready(function() {
  document.onkeypress = stopRKey;
  // catch the id of submit button and store-it to the form
  $("form").each(function() {
    var that = $(this);

    // define context and reference
    /* for each of the submit-inputs - in each of the forms on
			 the page - assign click and keypress event */
    $("input:submit,button", that).bind("click keypress", function(e) {
      // store the id of the submit-input on it's enclosing form
      that.data("callerid", this.id);
    });
  });

  $("#form1").submit(function(e) {
    var Origin_id = $(e.target).data("callerid");
    alert(Origin_id);
    e.preventDefault();

  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<form id="form1" name="form1" action="" method="post">
  <input type="text" name="text1" />
  <input type="submit" id="button1" value="Submit1" name="button1" />
  <button type="submit" id="button2" name="button2">
    Submit2
  </button>
  <input type="submit" id="button3" value="Submit3" name="button3" />
</form>

2
vasilenicusor

Semblable à Stan, mais répond: 

  • si vous avez plus d'un bouton, vous devez obtenir uniquement le premier bouton .__ => [0] 
  • si le formulaire peut être soumis avec la touche Entrée, vous devez gérer un défaut => myDefaultButtonId

$(document).on('submit', function(event) {
    event.preventDefault();
    var pressedButtonId = 
         typeof $(":input[type=submit]:focus")[0] === "undefined" ? 
         "myDefaultButtonId" :
         $(":input[type=submit]:focus")[0].id;
    ...
 }
2
yann-h

Cela m'a aidé https://stackoverflow.com/a/17805011/1029257

Formulaire soumis uniquement après avoir cliqué sur le bouton d'envoi.

var theBtn = $(':focus');
if(theBtn.is(':submit'))
{
  // ....
  return true;
}

return false;
1
w4kskl

Un moyen simple de distinguer le <bouton> ou le <type d'entrée = "bouton" ...> sur lequel on appuie est de vérifier son "id":

$("button").click(function() {
  var id = $(this).attr('id');
  ... 
});
0
Apostolos

Voici un exemple, qui utilise this.form pour obtenir le formulaire correct dans lequel est soumis, et des champs de données pour stocker le dernier élément sélectionné/ciblé. J'ai également inséré le code de soumission dans un délai d'attente afin de m'assurer que les événements de clic se produisent avant son exécution (certains utilisateurs ont signalé dans des commentaires que sur Chrome, un événement de clic était parfois déclenché après une soumission).

Fonctionne lorsque vous naviguez avec les touches et avec la souris/les doigts sans compter sur les navigateurs pour envoyer un événement de clic sur la touche RETOUR (cela ne fait pas de mal), j'ai ajouté un gestionnaire d'événements pour les événements de focus des boutons et des champs.

Vous pouvez ajouter des boutons de type = "submit" aux éléments qui se sauvegardent lorsque vous cliquez dessus.

Dans la démo, j'ai défini une bordure rouge pour afficher l'élément sélectionné et une alerte indiquant le nom, la valeur et le libellé.

Voici le violon

Et voici le (même) code:

Javascript:

$("form").submit(function(e) {
  e.preventDefault();
  // Use this for rare/buggy cases when click event is sent after submit
  setTimeout(function() {

    var $this=$(this);
    var lastFocus = $this.data("lastFocus");
    var $defaultSubmit=null;

    if(lastFocus) $defaultSubmit=$(lastFocus);

    if(!$defaultSubmit || !$defaultSubmit.is("input[type=submit]")) {
      // If for some reason we don't have a submit, find one (the first)
      $defaultSubmit=$(this).find("input[type=submit]").first();
    }

    if($defaultSubmit) {
      var submitName=$defaultSubmit.attr("name");
      var submitLabel=$defaultSubmit.val();

       // Just a demo, set hilite and alert
      doSomethingWith($defaultSubmit);
      setTimeout(function() {alert("Submitted "+submitName+": '"+submitLabel+"'")},1000);
    } else {
      // There were no submit in the form
    }

  }.bind(this),0);

});

$("form input").focus(function() {
  $(this.form).data("lastFocus", this);
});
$("form input").click(function() {
  $(this.form).data("lastFocus", this);
});

// Just a demo, setting hilite
function doSomethingWith($aSelectedEl) {
  $aSelectedEl.css({"border":"4px solid red"});
  setTimeout(function() { $aSelectedEl.removeAttr("style"); },1000);
}

DUMMY HTML:

<form>
<input type="text" name="testtextortexttest" value="Whatever you write, sir."/>
<input type="text" name="moretesttextormoretexttest" value="Whatever you write, again, sir."/>

<input type="submit" name="test1" value="Action 1"/>
<input type="submit" name="test2" value="Action 2"/>
<input type="submit" name="test3" value="Action 3"/>
<input type="submit" name="test4" value="Action 4"/>
<input type="submit" name="test5" value="Action 5"/>
</form>

DUMB CSS:

input {display:block}
0
FrancescoMM

Vous pouvez créer un type d’entrée = "masqué" en tant que titulaire pour une information d’identification de bouton.

<input type="hidden" name="button" id="button">
<input type="submit" onClick="document.form_name.button.value = 1;" value="Do something" name="do_something">

Dans ce cas, le formulaire transmet la valeur "1" (id de votre bouton) lors de l'envoi. Cela fonctionne si onClick se produit avant submit (?), Je ne suis pas sûr que ce soit toujours vrai.

0
darekk

J'écris cette fonction qui m'aide

var PupulateFormData= function (elem) {
var arr = {};
$(elem).find("input[name],select[name],button[name]:focus,input[type='submit']:focus").each(function () {
    arr[$(this).attr("name")] = $(this).val();
});
return arr;
};

et ensuite utiliser

var data= PupulateFormData($("form"));
0
BabiBN

J'ai aussi fait une solution, et ça marche plutôt bien: 
Il utilise jQuery et CSS


Tout d’abord, j’ai créé une classe CSS rapide, qu’elle soit intégrée ou dans un fichier séparé.

<style type='text/css'>
    .Clicked {
        /*No Attributes*/
    }
</style>


Ensuite, sur l'événement click d'un bouton du formulaire, ajoutez la classe CSS au bouton. Si le bouton a déjà la classe CSS, supprimez-la. (Nous ne voulons pas deux classes CSS [au cas où]).

    // Adds a CSS Class to the Button That Has Been Clicked.
    $("form :input[type='submit']").click(function () 
    {
        if ($(this).hasClass("Clicked"))
        {
            $(this).removeClass("Clicked");
        }
        $(this).addClass("Clicked");
    });


Maintenant, testez le bouton pour voir s'il a la classe CSS, si le bouton testé n'a pas le CSS, alors l'autre bouton le sera.

    // On Form Submit
    $("form").submit(function ()
    {
        // Test Which Button Has the Class
        if ($("input[name='name1']").hasClass("Clicked"))
        {
            // Button 'name1' has been clicked.
        }
        else
        {
           // Button 'name2' has been clicked.
        }
    });

J'espère que cela aide!

0
Jason Cidras