フォーム送信イベントから送信の原因となったボタンを取得するにはどうすればよいですか?


110

フォームの送信をトリガーした送信ボタンの値を見つけようとしています

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

});

ボタンごとに$( "input [type = submit]")。click()イベントを発生させて変数を設定することもできますが、送信時にフォームからボタンを引き出す方法ほどエレガントではありません。


2
そのようなボタンは必ずしも存在しないことに注意してください。スクリプトで実行できますformobj.submit()。クリックイベントが良い方法だと思います。
Jason Orendorff

1
最近のブラウザにはevent.submitter、クリックされた、<button>または<input type="submit">クリックされたブラウザが表示されます。
gfv

回答:


107

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にあります。

ハイパーフォームを使用している場合、これは送信をトリガーしたボタンにアクセスする方法です。

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

1
MDNは「はい」と言っています。(FF3、IE4、Chrome 2、Safari 4、Opera 9)
Boldewyn

1
これが答えです。
Royi Namir 2014

2
うーん...フォームが[Enter]で調停されている場合、これは機能しますか?Specはデフォルトの送信ボタンをクリックすることと同等であるべきだと述べていますが、それをアクティブな要素のままにするかどうかはわかりません。
Doin

8
残念ながら、「送信機」を定義できるため、だけに依存することはできませんactiveElement。A. 本物のクリックによるアクティブ化(マウスまたはキーボードで直接クリックするSpace / Enter)。B. 合成クリックのアクティブ化を介して(buttonElement.click()またはbuttonElement.dispatch(new MouseEvent(...))、フォーカスを取得せずに); C. フォームを介して暗黙的に送信(他のフォームのフィールドとのキーボード操作)D.なし、いつformElement.submit()
mems

5
最新のものを維持するためのメモ。現時点では、送信ボタンをクリックすると、SafariはactiveElementをドキュメント本文に設定します。私はSafari 9.1でこの問題に遭遇しました
coderkevin

35

私はこれを実装しましたが、そうなると思います。

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

回答ありがとうございますが、これはそれほどエレガントではありません...


1
クロスブラウザ/複数の送信ボタンには対応していません。
user1610743 14

2
フォーム送信イベントの前にクリックイベントがトリガーされることが保証されていますか?フォームにdoNotSubmitクラスを与えることをお勧めします。サブミット関数内でクラスが存在しないかどうかをチェックし(そうでない場合はサブミットしない)、クリックイベント内でフォームクラスdoNotSubmitを削除して$( ''。myForm ')。triggerを実行します。 ('参加する'); 送信ボタンの値を非表示フィールドとして追加した後
Hafenkranich

2
@Hafenkranich Chromeでまれに、送信イベントの後にクリックイベントがトリガーされます。
romanoza 2016年

@roamnozaそれもまさに私が遭遇したものです。
Hafenkranich 2016年

2
@ j4k3より良いソリューションを手に入れましたか?この回答は8歳です
ハンター、

10

私はテストフォームを作成し、Firebugを使用してこの方法で値を取得しました。

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

残念ながら、Firefoxのみがこのイベントをサポートしています。


5
IEにはこのプロパティはありません(explicitOriginalTarget)
andres descalzo 2010年

1
古き良きIEがそれをめちゃくちゃにし、Firebugを通過し、他に使用するオブジェクト値を見つけることができませんでしたが、代替ブラウザーについては忘れていました。それはそうではないと聞いても驚かないで、Chromeをチェックする必要があります。
デイブアンダーソン

11
Firefoxのみがこのイベントをサポートしています。
Andy E

つまり、基本的に、JSで実行できない HTMLの何かがあります... Mozillaは欠落している機能を実装することを決定し、誰もそれに追随していませんか?これが私たちが良いものを手に入れることができない理由です
aross

6

私の目的にとってよりクリーンに見えるアプローチは次のとおりです。

まず、すべてのフォームについて:

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

このクリックイベントがフォームに対して発生すると、後でアクセスされる元のターゲット(イベントオブジェクトで使用可能)が記録されるだけです。フォーム上のどこをクリックしても発火するため、これはかなり広いストロークです。最適化のコメントは歓迎しますが、目立った問題が発生することはないと思います。

次に、$( 'form')。submit()で、最後にクリックされたものを問い合わせることができます。

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

6

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

4

このリンクによれば、Eventオブジェクトには次のフィールドが含まれていますEvent.target

イベントを開始したオブジェクトを表す文字列を返します。

その値が何であるかをテストするページを作成したところ、その表現は、クリックされたボタンではなく、フォーム自体に対するもののように見えます。つまり、JavaScriptはクリックされたボタンを判別する機能を提供していません。

Dave Andersonのソリューションに関する限り、複数のブラウザーでテストしてから使用することをお勧めします。うまくいく可能性もありますが、どちらとも言えません。


1
targetフォーム全体を返します。したがって、残念ながら正しい送信ボタンを検出するのに役立ちません。
Hafenkranich

私の回答では、@ Hafenkranichと同じくらい言っています。
cmptrgeekken 2016

Event.target文字列ではありません。これはEventTargetオブジェクトであり、この場合は送信されたフォーム自体です。
Akseli

4

クリーンな方法の1つは、各フォームボタンでクリックイベントを使用することです。以下は、保存、キャンセル、削除ボタンを備えた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;
   });

3

送信ボタンを取得する方法をいくつか検索して見つけましたname+value jQueryの+ AJAXを使用してサーバーに送信します。あまり気に入らなかった...

最高の1つはここに提示されたハンターのソリューションでした!

しかし、私は自分で別のものを書きました。

共有したいのですが、それは良いことであり、必要に応じて、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ます。

編集:以下のバージョンは読みやすくなっています。また、以前に追加された非表示フィールドの削除も処理します(同じフォームを2回送信する場合、これは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);
});

1+これでうまくいきました。ありがとう!
Lennart Rolland 2012年

これは<button/>、同じname属性を共有するすべてのに依存しているようです。私はクラスを使用し、あなたの中でそれを参照します.remove()
binki 2013

@binki:いいえ、ありません。とにかく、各開発者はソリューションを自分のニーズに適合させることができます。
J.ブルーニ2013

jsfiddle.net/binki/d8ecvは、name属性に関する私の意味を示しています。フォームが再利用され、異なる名前の送信入力が含まれている場合、古い入力によってフォームが乱雑になる可能性があります。
binki 2013

わかりました...回答を更新します。(実際、コードで使用されている<button/>間、要素について言及しているという無関係な事実のため、コメントにはあまり注意を払いませんでした<input type="submit" />...)
J. Bruni

2

提供されているいくつかの例を試しましたが、それらは私たちの目的には機能しませんでした。

表示するフィドルは次のとおりです。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
    });
});

2

(イベント)

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;">

1

「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>

"yikes" ?、機能する、機能しない、役立つ、役に立たない、...?、私は良い英語を話さない
アンドレスdescalzo

@hunterコメントを複数回投票するにはどうすればよいですか。
トムオージェ2016年

0

jQueryは、送信イベントに関するデータを提供していないようです。あなたが提案した方法があなたの最善の策であるように見えます。


0

他の人が私の要件を満たしていないので、ちょうど別のソリューション。利点は、クリックとキープレス(Enterおよびスペース)が検出されることです。

// 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({
            // ...
        })
    }
}

これは私にとって最も効果的でした。


0

より具体的なイベントハンドラーとJQueryでは、イベントオブジェクトはクリックされたボタンです。必要に応じて、このイベントから委任フォームを取得することもできます。

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

このドキュメントには、開始するために必要なものがすべて含まれています。 JQuery Doc


0

私を助けるこの関数を書きます

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"));
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.