Bagaimana saya bisa mendapatkan tombol yang menyebabkan pengiriman dari acara pengiriman formulir?

110

Saya mencoba menemukan nilai tombol kirim yang memicu formulir untuk dikirim

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

});

Saya mungkin dapat mengaktifkan peristiwa $ ("input [type = submit]"). Click () untuk setiap tombol dan menetapkan beberapa variabel, tetapi itu tampaknya kurang elegan daripada cara menarik tombol dari formulir saat kirim.

pemburu
sumber
2
Perhatikan bahwa belum tentu ada tombol seperti itu. Skrip mungkin bisa formobj.submit(). Saya pikir acara klik adalah cara yang tepat.
Jason Orendorff
1
Untuk browser modern sekarang ada event.submitteryang memberi Anda <button>atau <input type="submit">yang diklik.
gfv

Jawaban:

107

Saya memanfaatkan document.activeElementseperti yang digambarkan dalam jawaban ini: Bagaimana cara mendapatkan elemen fokus dengan 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 */
    }
});

Saya memanfaatkan fakta, bahwa tombol selalu menjadi elemen fokus setelah mengkliknya. Ini tidak akan berhasil, jika Anda melakukan yang blur()benar setelah klik.

@Doin telah melihat kelemahan lain. Jika pengguna mengirimkan formulir melalui enterdi bidang teks, document.activeElementtidak disetel. Anda harus berhati-hati untuk ini sendiri, dengan menangani keypressperistiwa di dalam input[type="text"]dan serupa.

Pembaruan 2017-01: Untuk perpustakaan saya Hyperform, saya memilih untuk tidak menggunakan activeElementtetapi untuk menangkap semua acara, yang mengarah ke pengiriman formulir. Kode untuk ini ada di Github.

Jika Anda kebetulan menggunakan Hyperform, berikut cara Anda mengakses tombol yang memicu pengiriman:

$(form).on('submit', function(event) {
  var button = event.submittedVia;
});
Boldewyn
sumber
1
MDN mengatakan ya. (FF3, IE4, Chrome 2, Safari 4, Opera 9)
Boldewyn
1
Ini harus menjadi jawabannya.
Royi Namir
2
Hmmm ... apakah ini berfungsi jika formulir dikirim melalui [Enter]? Spec mengatakan itu harus setara dengan mengklik tombol kirim default, tapi saya tidak yakin itu meninggalkannya sebagai elemen aktif atau tidak.
Lakukan
8
Sayangnya, Anda tidak dapat hanya mengandalkanactiveElement , karena "pengirim" dapat didefinisikan: A. Melalui aktivasi klik otentik (diklik langsung dengan mouse atau keyboard Spasi / Enter); B. Melalui aktivasi klik sintetis ( buttonElement.click()atau buttonElement.dispatch(new MouseEvent(...)), tanpa mendapatkan fokus); C. via formulir secara implisit pengiriman (interaksi keyboard dengan bidang formulir lain) D. ke tidak ada, ketikaformElement.submit()
mems
5
Hanya catatan untuk menjaga hal-hal terkini. Saat ini, Safari menyetel activeElement ke badan dokumen saat mengklik tombol kirim. Saya mengalami masalah ini di Safari 9.1
coderkevin
35

Saya menerapkan ini dan saya kira itu akan berhasil.

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

    var val = $("input[type=submit][clicked=true]").val()

    // DO WORK

});

dan ini adalah acara tombol kirim yang menyiapkannya

$("form input[type=submit]").click(function() {
    $("input[type=submit]", $(this).parents("form")).removeAttr("clicked");
    $(this).attr("clicked", "true");
});

Terima kasih atas tanggapannya, tapi ini tidak terlalu aneh ...

pemburu
sumber
1
Tidak dapat melakukan crossbrowser / beberapa tombol kirim.
pengguna1610743
2
Apakah dijamin bahwa peristiwa klik dipicu sebelum peristiwa pengiriman formulir? Saya menyarankan untuk memberikan formulir doNotSubmitkelas, di dalam fungsi kirim periksa apakah kelas tersebut tidak ada (jika tidak jangan kirimkan), di dalam acara klik hapus kelas formulir doNotSubmitdan lakukan pemicu $ (''. MyForm '). ('Kirimkan'); setelah menambahkan nilai tombol kirim sebagai bidang tersembunyi
Hafenkranich
2
@Hafenkranich Pada beberapa kesempatan langka di Chrome, peristiwa klik dipicu SETELAH acara kirim.
romanoza
@roamnoza itulah yang saya temui juga.
Hafenkranich
2
@ j4k3 Punya solusi yang lebih baik? Jawabannya adalah 8 tahun
pemburu
10

Saya membuat formulir uji dan menggunakan Firebug menemukan cara ini untuk mendapatkan nilainya;

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

Sayangnya, hanya Firefox yang mendukung acara ini.

Dave Anderson
sumber
5
IE tidak memiliki properti ini (eksplisitOriginalTarget)
andres descalzo
1
IE lama yang baik mengacaukannya, melewati Firebug dan tidak dapat melihat nilai objek lain untuk digunakan tetapi lupa tentang browser alternatif. Tidak heran mendengarnya tidak, harus memeriksa Chrome.
Dave Anderson
11
Hanya Firefox yang mendukung acara ini.
Andy E
Jadi pada dasarnya, ada sesuatu dalam HTML yang tidak dapat dilakukan di JS ... Mozilla memutuskan untuk menerapkan fitur yang hilang, dan tidak ada yang mengikutinya? Inilah sebabnya mengapa kita tidak dapat memiliki hal
aross
7

Sekarang ada submitterproperti standar dalam acara kirim.
Sudah diterapkan di Firefox 75 !

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

Untuk browser yang tidak mendukungnya, gunakan polyfill ini :

!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);
}();
Tobias Buschor
sumber
6

Inilah pendekatan yang tampaknya lebih bersih untuk tujuan saya.

Pertama, untuk segala bentuk:

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

Saat peristiwa klik ini diaktifkan untuk sebuah formulir, itu hanya mencatat target asal (tersedia di objek peristiwa) untuk diakses nanti. Ini adalah goresan yang cukup luas, karena akan diaktifkan untuk setiap klik di mana pun pada formulir. Komentar pengoptimalan diterima, tetapi saya curiga itu tidak akan pernah menimbulkan masalah yang nyata.

Kemudian, di $ ('form'). Submit (), Anda dapat menanyakan apa yang terakhir diklik, dengan sesuatu seperti

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

Menurut tautan ini , objek acara berisi bidang Event.target, yang:

Mengembalikan string yang mewakili objek yang memulai acara.

Saya baru saja membuat halaman yang menguji apa nilai itu, dan tampaknya representasi itu untuk formulir itu sendiri, bukan untuk tombol yang diklik. Dengan kata lain, Javascript tidak menyediakan fasilitas untuk menentukan tombol yang diklik.

Sejauh solusi Dave Anderson , mungkin ada baiknya untuk mengujinya di beberapa browser sebelum menggunakannya. Mungkin saja itu bisa bekerja dengan baik, tapi saya tidak bisa mengatakannya.

cmptrgeekken.dll
sumber
1
The targetmengembalikan seluruh bentuk. Jadi sayangnya tidak membantu untuk mendeteksi tombol kirim yang tepat.
Hafenkranich
Saya mengatakan sebanyak itu dalam jawaban saya, @Hafenkranich.
cmptrgeekken
Event.targetbukanlah sebuah string. Itu sebuah EventTargetobjek, yang dalam hal ini adalah formulir yang dikirimkan itu sendiri.
Akseli
4

Salah satu pendekatan bersih adalah dengan menggunakan acara klik pada setiap tombol formulir. Berikut adalah formulir html dengan tombol simpan, batalkan dan hapus:

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

Berikut ini adalah jquery tersebut. Saya mengirim 'tindakan' yang sesuai ke fungsi server yang sama tergantung pada tombol mana yang diklik ('simpan' atau 'hapus'). Jika 'batal', diklik, saya baru saja memuat ulang halaman.

$('.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;
   });
pengguna1128563
sumber
3

Saya mencari dan menemukan beberapa cara untuk mendapatkan tombol kirim name+ valuedikirim ke server menggunakan jQuery + AJAX. Saya tidak begitu menyukai mereka ...

Salah satu yang terbaik adalah solusi pemburu yang disajikan di sini!

Tapi saya sendiri yang menulis satu sama lain.

Saya ingin berbagi, karena itu bagus, dan, sesuai kebutuhan, ini berfungsi juga dengan formulir yang dimuat melalui ajax (setelah 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'));
});

Sederhana! Saat tombol kirim diklik, bidang tersembunyi ditambahkan ke formulir, menggunakan sama namedanvalue tombol yang kirim.

EDIT: Versi di bawah ini lebih mudah dibaca. Juga, ini menangani penghapusan bidang tersembunyi yang ditambahkan sebelumnya (dalam kasus mengirimkan formulir yang sama dua kali, yang sangat mungkin saat menggunakan AJAX).

Kode yang ditingkatkan:

$(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);
});
J. Bruni
sumber
1+ Ini berhasil untuk saya. Terima kasih!
Lennart Rolland
Sepertinya ini bergantung pada semua <button/>yang berbagi nameatribut yang sama . Saya akan menggunakan kelas dan mengacu pada kelas Anda .remove().
binki
@binki: tidak, tidak. Bagaimanapun, setiap pengembang dapat menyesuaikan solusi dengan kebutuhannya sendiri.
J. Bruni
jsfiddle.net/binki/d8ecv menunjukkan apa yang saya maksud tentang nameatribut. Jika formulir digunakan kembali dan berisi masukan pengiriman dengan nama berbeda, masukan lama dapat mengacaukan formulir.
binki
Sekarang saya mengerti ... Saya akan memperbarui jawaban saya. (Faktanya, saya tidak terlalu memperhatikan komentar Anda karena fakta yang tidak terkait bahwa Anda menyebutkan <button/>elemen, sementara <input type="submit" />digunakan dalam kode ...)
J. Bruni
2

Saya memang mencoba beberapa contoh yang diberikan, tetapi tidak berhasil untuk tujuan kami.

Ini biola untuk ditunjukkan: http://jsfiddle.net/7a8qhofo/1/

Saya dihadapkan pada masalah serupa, dan inilah cara kami menyelesaikan masalah dalam formulir kami.

$(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
    });
});
Rudi Strydom
sumber
2

(acara)

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;">
pengguna3126867
sumber
1

Anda dapat mencoba cara ini dengan "event.originalEvent.x" dan "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>
andres descalzo
sumber
"yikes" ?, berhasil, tidak berfungsi, berguna, tidak berguna, ...? , Saya tidak berbicara bahasa Inggris dengan baik
andres descalzo
@ Pemburu bagaimana cara meningkatkan komentar Anda beberapa kali?
Tom Auger
0

jQuery tampaknya tidak memberikan data itu pada acara kirim. Sepertinya metode yang Anda usulkan adalah yang terbaik.

Matchu
sumber
0

Hanya solusi lain karena tidak ada yang lain yang memenuhi persyaratan saya. Keuntungannya adalah, klik dan penekanan tombol (masuk dan spasi) terdeteksi.

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

Ini bekerja paling baik untuk saya.

roland
sumber
0

Dengan event handler dan JQuery yang lebih spesifik, objek event Anda adalah tombol yang diklik. Anda juga bisa mendapatkan formulir delegasi dari acara ini jika diperlukan.

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

Dokumen ini memiliki semua yang Anda butuhkan untuk memulai. Dok JQuery .


sumber
0

Saya menulis fungsi ini yang membantu saya

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;

};

dan kemudian Gunakan

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

Ada properti pengirim untuk SubmitEvent formulir . Namun, untuk saat ini, ini tidak berfungsi di 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);
}

Pendekatan berbeda yang berfungsi di semua browser. Namun, Anda harus mengandalkan formelemen alih-alih eventobjeknya. Ini pada dasarnya menambahkan properti 'pengirim' ke objek elemen formulir yang dapat direferensikan nanti saat pengiriman formulir.

<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);
}
Nur Ilyas
sumber