Как я могу получить кнопку, которая вызвала отправку из формы отправки события?

Я пытаюсь найти значение кнопки отправки, которая вызвала форму для отправки

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

});

Я мог бы вызвать событие $("input[type=submit]"). Click() для каждой кнопки и установить некоторую переменную, но это выглядит менее элегантно, чем то, как выдергивание кнопки из формы при отправке.

22 ответа

Решение

Я реализовал это, и я предполагаю, что это будет делать.

$(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");
});

Спасибо за ответы, но это не ужасно не элегантно...

Я использовал document.activeElement как показано в этом ответе: как получить сфокусированный элемент с помощью jQuery?

$form.on('submit', function() {
    var $btn = $(document.activeElement);

    if (
        /* there is an activeElement at all */
        $btn.length &&

        /* it's a child of the form */ 
        $form.has($btn) &&

        /* it's really a submit element */
        $btn.is('button[type="submit"], input[type="submit"], input[type="image"]') &&

        /* it has a "name" attribute */
        $btn.is('[name]')
    ) {
        console.log("Seems, that this element was clicked:", $btn);
        /* access $btn.attr("name") and $btn.val() for data */
    }
});

Я пользуюсь тем фактом, что кнопка всегда является сфокусированным элементом после нажатия на нее. Это не будет работать, если вы делаете blur() сразу после клика.

@ Doin обнаружил еще один недостаток. Если пользователь отправляет форму через enter в текстовом поле document.activeElement не установлен. Вам нужно следить за этим самостоятельно, обрабатывая keypress события в input[type="text"] и тому подобное.

Обновление 2017-01: для моей библиотеки Hyperform я решил не использовать activeElement но поймать все события, которые приводят к отправке формы. Код для этого на Github.

Если вы используете Hyperform, вы получите доступ к кнопке, которая вызвала отправку:

$(form).on('submit', function(event) {
  var button = event.submittedVia;
});

Теперь есть стандарт submitterсвойство в событии отправки.
Уже реализовано в Firefox 75!

document.addEventListener('submit',function(e){
    console.log(e.submitter)
})

Для браузеров, которые его не поддерживают, используйте этот полифилл:

!function(){
    var lastBtn = null
    document.addEventListener('click',function(e){
        if (!e.target.closest) return;
        lastBtn = e.target.closest('button, input[type=submit]');
    }, true);
    document.addEventListener('submit',function(e){
        if ('submitter' in e) return;
        var canditates = [document.activeElement, lastBtn];
        for (var i=0; i < canditates.length; i++) {
            var candidate = canditates[i];
            if (!candidate) continue;
            if (!candidate.form) continue;
            if (!candidate.matches('button, input[type=button], input[type=image]')) continue;
            e.submitter = candidate;
            return;
        }
        e.submitter = e.target.querySelector('button, input[type=button], input[type=image]')
    }, true);
}();

Я создал тестовую форму и с помощью Firebug нашел способ получить значение;

$('form').submit(function(event){
  alert(event.originalEvent.explicitOriginalTarget.value);
}); 

К сожалению, только Firefox поддерживает это событие.

Вот подход, который кажется чище для моих целей.

Во-первых, для любой формы:

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

Когда это событие щелчка запускается для формы, оно просто записывает исходную цель (доступную в объекте события), к которой можно получить доступ позже. Это довольно широкий штрих, так как он будет срабатывать при любом щелчке в любом месте формы. Комментарии по оптимизации приветствуются, но я подозреваю, что это никогда не вызовет заметных проблем.

Затем, в $('form'). Submit(), вы можете узнать, что в последний раз щелкнуло, с чем-то вроде

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

Один чистый подход заключается в использовании события click на каждой кнопке формы. Ниже приведена HTML-форма с кнопками сохранения, отмены и удаления:

<form  name="formname" action="/location/form_action" method="POST">
<input name="note_id" value="some value"/>
<input class="savenote" type="submit" value="Save"/>
<input class="cancelnote" type="submit" value="Cancel"/>
<input class="deletenote" type="submit" value="Delete" />
</form> 

Ниже приводится JQuery. Я отправляю соответствующее "действие" на ту же серверную функцию в зависимости от того, какая кнопка была нажата ("сохранить" или "удалить"). Если нажать кнопку "Отмена", я просто перезагружаю страницу.

$('.savenote').click(function(){
   var options = {
       data: {'action':'save'}
   };
   $(this).parent().ajaxSubmit(options);
   });


$('.deletenote').click(function(){
   var options = {
       data: {'action':'delete'}
   };
   $(this).parent().ajaxSubmit(options);
   });


$('.cancelnote').click(function(){
   window.location.reload(true);
   return false;
   });

По этой ссылке объект Event содержит поле Event.target, который:

Возвращает строку, представляющую объект, который инициировал событие.

Я только что создал страницу, проверяющую, что это за значение, и кажется, что это представление для самой формы, а не для нажатой кнопки. Другими словами, Javascript не предоставляет средства для определения нажатой кнопки.

Что касается решения Дейва Андерсона, было бы неплохо проверить его в нескольких браузерах перед его использованием. Вполне возможно, что это могло бы работать нормально, но я не могу сказать в любом случае.

Там есть податель свойство для формы в SubmitEvent. Однако в настоящее время это не работает в Safari.

<form id="form">
    <button value="add" type="submit">Add</button>
    <button value="remove" type="submit">Remove</button>
</form>
let form = document.getElementById('form');

form.onsubmit = (event) => {
    e.preventDefault();
    console.log(e.submitter.type);
}

Другой подход, который работает во всех браузерах. Однако вы должны положиться наform элемент вместо eventобъект. Это в основном добавляет свойство "submitter" к объекту элемента формы, на которое можно ссылаться позже при отправке формы.

<form id="form">
    <button onclick="this.form.submitter = 'add'" type="submit">Add</button>
    <button onclick="this.form.submitter = 'remove'" type="submit">Remove</button>
</form>
let form = document.getElementById('form');

form.onsubmit = (event) => {
    e.preventDefault();
    console.log(form.submitter);
}

(событие)

function submForm(form,event){
             var submitButton;

             if(typeof event.explicitOriginalTarget != 'undefined'){  //
                 submitButton = event.explicitOriginalTarget;
             }else if(typeof document.activeElement.value != 'undefined'){  // IE
                 submitButton = document.activeElement;
             };

             alert(submitButton.name+' = '+submitButton.value)
}


<form action="" method="post" onSubmit="submForm(this, event); return false;">

Я искал и нашел несколько способов получить кнопку отправки name + value отправлено на сервер с помощью jQuery + AJAX. Мне они не очень понравились...

Одним из лучших было решение охотника, представленное здесь!

Но я написал еще один сам.

Я хочу поделиться, потому что это хорошо, и, как мне было нужно, он работает также с формами, загруженными через ajax (после document.ready):

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

Просто! При нажатии кнопки "Отправить" в форму добавляется скрытое поле, используя тот же name а также value кнопки отправки.

РЕДАКТИРОВАТЬ: Версия ниже легче читать. Кроме того, он заботится об удалении ранее добавленных скрытых полей (в случае отправки одной и той же формы дважды, что вполне возможно при использовании AJAX).

Улучшенный код:

$(document).on('click', 'form input[type=submit]', function(){
    var name   = $(this).attr('name');
    if (typeof name == 'undefined') return;
    var value  = $(this).attr('value');
    var $form  = $(this).parents('form').first();
    var $input = $('<input type="hidden" class="temp-hidden" />').attr('name', name).attr('value', value);
    $form.find('input.temp-hidden').remove();
    $form.append($input);
});

Получить объект-отправитель из объекта события

Вы можете просто получить объект события при отправке формы. Из этого получите объект-отправитель. Как показано ниже:

      $(".review-form").submit(function (e) {
        e.preventDefault(); // avoid to execute the actual submit of the form.

        let submitter_btn = $(e.originalEvent.submitter);
        
        console.log(submitter_btn.attr("name"));
}

Я подробно объяснил вот здесь: ( /questions/27803571/jquery-kak-uznat-kakaya-knopka-byila-nazhata-pri-otpravke-formyi/56765757#56765757)
Дайте мне знать, если у вас есть какие-либо сомнения.

Я попробовал некоторые из приведенных примеров, но они не работали для наших целей.

Вот скрипка, чтобы показать: http://jsfiddle.net/7a8qhofo/1/

Я столкнулся с аналогичной проблемой, и именно так мы решили проблему в наших формах.

$(document).ready(function(){

    // Set a variable, we will fill later.
    var value = null;

    // On submit click, set the value
    $('input[type="submit"]').click(function(){
        value = $(this).val();
    });

    // On data-type submit click, set the value
    $('input[type="submit"][data-type]').click(function(){
        value = $(this).data('type');
    });

    // Use the set value in the submit function
    $('form').submit(function (event){
        event.preventDefault();
        alert(value);
        // do whatever you need to with the content
    });
});

Вы можете попробовать этот способ с помощью "event.originalEvent.x" и "event.originalEvent.y":

<!DOCTYPE html>
<html>
<head>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script> 
    <title>test</title>
</head>
<body>

    <form id="is_a_form">
        <input id="is_a_input_1" type="submit"><br />
        <input id="is_a_input_2" type="submit"><br />
        <input id="is_a_input_3" type="submit"><br />
        <input id="is_a_input_4" type="submit"><br />
        <input id="is_a_input_5" type="submit"><br />
    </form>

</body>
</html>
<script>
$(function(){

    $.fn.extend({
      inPosition: function(x, y) {

        return this.each(function() {

            try{
                var offset = $(this).offset();

                if ( (x >= offset.left) &&
                     (x <= (offset.left+$(this).width())) &&
                     (y >= offset.top) &&
                     (y <= (offset.top+$(this).height())) )
                {
                    $(this).css("background-color", "red");
                }
                else
                {
                        $(this).css("background-color", "#d4d0c8");
                }
                }
                catch(ex)
                {
                }

        });
      }
    }); 

    $("form").submit(function(ev) {

        $("input[type='submit']").inPosition(ev.originalEvent.x ,ev.originalEvent.y);
        return false;

    });

});
</script>

Вы можете получить идентификатор кнопки из следующего HTML-кода:

      <form id="theForm" action="" method="POST">
  <button name="sbtn" id="sbtn" value="Hey button" type="submit">Submit</button>
</form>

используя следующий JavaScript (используя атрибут .val()):

      $('#theForm').on('click', 'button', function (e) {
  e.preventDefault();
  var
    $button = $(e.target),
    $form = $(e.delegateTarget);
  var buttonValue = $button.val();
});

С более конкретным обработчиком событий и JQuery, ваш объект события - нажатие кнопки. Вы также можете получить делегирующую форму из этого события, если это необходимо.

$('form').on('click', 'button', function (e) {
  e.preventDefault();
  var
    $button = $(e.target),
    $form = $(e.delegateTarget);
  var buttonValue = $button.val();
});

В этом документе есть все, что вам нужно для начала. JQuery Док.

Просто другое решение, так как никто другой не отвечал моим требованиям. Преимущество состоит в том, что обнаруживаются щелчок и нажатие клавиши (ввод и пробел).

// Detects the Events
var $form = $('form');
$form.on('click keypress', 'button[type="submit"]', function (ev) {

    // Get the key (enter, space or mouse) which was pressed.
    if (ev.which === 13 || ev.which === 32 || ev.type === 'click') {

        // Get the clicked button
        var caller = ev.currentTarget;

        // Input Validation
        if (!($form.valid())) {
            return;
        }

        // Do whatever you want, e.g. ajax...
        ev.preventDefault();
        $.ajax({
            // ...
        })
    }
}

Это сработало лучше для меня.

При работе с веб-компонентами, в которых элементы формы находятся в shadowRoot, я адаптировал превосходный полифил Тобиаса Бушора следующим образом, чтобы он работал следующим образом через импортированный модуль. Обратите внимание, что это обеспечивает совместимость только с вечнозелеными клиентами -edge, safari, chrome, firefox.

      if( !('SubmitEvent' in self && 'submitter' in SubmitEvent.prototype) ){
// polyfill SubmitEvent.submitter (a Safari issue as-of 2021)
// https://developer.mozilla.org/docs/Web/API/SubmitEvent
    const submitter = Symbol.for('submitter');
    Event[ submitter ] = null;
    const submitterSelector = 'input[type=submit], input[type=image], input[type=button], button';

    Object.defineProperty(Event.prototype, 'submitter', {
        get: function(){
            if('submit' === this.type){
                let node = Event[ submitter ];
                const form = this.target;
                if(!node || !form.contains(node)){
                    node = form.querySelector(submitterSelector);
                }
                // always return a node, default as though form.submit called
                return node || form;
            }
            return undefined;
        },
        set: function(value){
            if('submit' === this.type){
                this.submitter = value;
            }
        }
    });
    self.addEventListener('click', function polyfill_SubmitEvent_submitter_click(event){
        const node = event.composedPath()[0];
        const closest = node.closest?.(submitterSelector) ?? null;
        Event[ submitter ] = closest;
    }, true);
}

Кажется, jQuery не предоставляет эти данные о событии submit. Похоже, предложенный вами метод - ваш лучший выбор.

Я наконец смог найти полный и простой ответ на вопрос: как я могу получить кнопку, которая вызвала отправку из события отправки формы?

Я приведу вам простой пример:

КОД HTML : форма

      <form id="myForm" enctype="multipart/form-data" method="post">

  ...
  all input, select, textarea ...
  ....

  <button id="bt1" value="add" type="submit">Add</button>
  <button id="bt2" value="back" type="submit">Back</button>
  <button id="bt3" value="remove" type="submit">Remove</button>
  <button id="bt4" value="register" type="submit">Register</button>
</form>

CODE JAVASCRIPT: прослушиватель событий и действия

      var myFctSubmit = function(event){
   var myTarget = event.target || event.srcElement;
   var myButton = event.originalEvent.submitter;

   var balise_form = $(myTarget).attr('id');
   var balise_button = $(myButton).attr('id');

   //Now you know the button and
   //you can apply the script you want...
   //here in this exemple :
   //balise_form = myForm
   //balise_button = {button that you click}

}

$('#myForm').bind('submit',myFctSubmit);

Следовательно, решение этой проблемы состоит в том, чтобы получить следующий элемент:

event.originalEvent.submitter

Всем удачи

Без jquery

      submit(e){
    console.log(e.nativeEvent.submitter)
}

Я пишу эту функцию, которая мне помогает

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;

};

а затем используйте

var data= PupulateFormData($("form"));
Другие вопросы по тегам