Przechwyć formularz przesłany w języku JavaScript i uniemożliwi normalne przesyłanie

84

Wydaje się, że istnieje wiele informacji o tym, jak przesłać formularz przy użyciu javascript, ale szukam rozwiązania, które pozwoli uchwycić, kiedy formularz został przesłany i przechwycić go w javascript.

HTML

<form>
 <input type="text" name="in" value="some data" />
 <button type="submit">Go</button>
</form>

Gdy użytkownik naciśnie przycisk przesyłania, nie chcę, aby formularz był przesyłany, ale zamiast tego chcę, aby została wywołana funkcja JavaScript.

function captureForm() {
 // do some stuff with the values in the form
 // stop form from being submitted
}

Szybkim hackem byłoby dodanie funkcji onclick do przycisku, ale nie podoba mi się to rozwiązanie ... istnieje wiele sposobów na przesłanie formularza ... np. Naciśnięcie klawisza powrotu na wejściu, czego to nie uwzględnia.

Ty

mrwooster
źródło
3
Możliwy duplikat Jak zapobiec przesyłaniu formularza?
Michał Perłakowski

Odpowiedzi:

96
<form id="my-form">
    <input type="text" name="in" value="some data" />
    <button type="submit">Go</button>
</form>

W JS:

function processForm(e) {
    if (e.preventDefault) e.preventDefault();

    /* do what you want with the form */

    // You must return false to prevent the default form behavior
    return false;
}

var form = document.getElementById('my-form');
if (form.attachEvent) {
    form.attachEvent("submit", processForm);
} else {
    form.addEventListener("submit", processForm);
}

Edycja : moim zdaniem to podejście jest lepsze niż ustawianie onSubmitatrybutu w formularzu, ponieważ zachowuje oddzielenie znacznika od funkcjonalności. Ale to tylko moje dwa centy.

Edit2 : Zaktualizowałem mój przykład, aby uwzględnićpreventDefault()

Michael McTiernan
źródło
to nie działa z chromem, o ile widzę, używając jsbin.com/ejoyas
Eiyrioü von Kauyf
2
Należy pamiętać, że kod zdarzenia attach należy wykonać PO udostępnieniu formularza w domenie. Na przykład użycie window.onload=function() { ... }do zawijania
mplungjan
kiedy processform()funkcja zostanie nazwana sir?
Nie jestem pewien, ponieważ nie używam IE, ale myślę, że parametr attachEvent powinien mieć wartość „onsubmit”.
Gerard ONeill
to nie działa w chrome 46, błąd przy dołączaniu wydarzenia, najpierw trzeba wczytać stronę
tsukimi
29

Nie możesz dołączać zdarzeń przed załadowaniem elementów, do których je dołączyłeś

To działa -

Zwykły JS

PRÓBNY

Zalecane użycie eventListener

// Should only be triggered on first page load
console.log('ho');

window.addEventListener("load", function() {
  document.getElementById('my-form').addEventListener("submit", function(e) {
    e.preventDefault(); // before the code
    /* do what you want with the form */

    // Should be triggered on form submit
    console.log('hi');
  })
});
<form id="my-form">
  <input type="text" name="in" value="some data" />
  <button type="submit">Go</button>
</form>

ale jeśli nie potrzebujesz więcej niż jednego słuchacza, możesz użyć onload i onsubmit

// Should only be triggered on first page load
console.log('ho');

window.onload = function() {
  document.getElementById('my-form').onsubmit = function() {
    /* do what you want with the form */

    // Should be triggered on form submit
    console.log('hi');
    // You must return false to prevent the default form behavior
    return false;
  }
}
    <form id="my-form">
      <input type="text" name="in" value="some data" />
      <button type="submit">Go</button>
    </form>

jQuery

// Should only be triggered on first page load
console.log('ho');

$(function() {
  $('#my-form').on("submit", function(e) {
    e.preventDefault(); // cancel the actual submit

    /* do what you want with the form */

    // Should be triggered on form submit

    console.log('hi');
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="my-form">
  <input type="text" name="in" value="some data" />
  <button type="submit">Go</button>
</form>

mplungjan
źródło
Myślę, że masz na myśli: $ ('# mój-formularz) .on (' wyślij ', funkcja () {alert (' cześć ');});
Michiel
1
@Michiel, chociaż to, co dostarczasz, jest tym, czego używasz z jQuery, to dostarczone rozwiązanie jest czystym rozwiązaniem JS bez zależności od jQuery. Rozwiązanie tutaj byłoby podobne do użycia<form onsubmit="alert('hi'); return false;">
Chris Marisic
2
@ChrisMarisic - kilka lat :) I tak zaktualizowałem odpowiedź, aby zawierała jQuery
mplungjan.
17

<form onSubmit="return captureForm()"> to powinno wystarczyć. Upewnij się, że captureForm()metoda zwraca false.

kba
źródło
Kontynuacja: czy istnieje sposób na przechwycenie przesłanego formularza za pomocą JavaScript bez wpływu na obsługę wymaganego atrybutu przez przeglądarkę?
Elisabeth
@Elisabeth Jakie traktowanie jakiego atrybutu? Jeśli masz na myśli nie zapobiegają formularz z rzeczywiście złożony, wystarczy captureForm(), aby powrócić truezamiast false.
kba
Obsługa przez przeglądarkę atrybutu „required”. Chcę uniemożliwić przesłanie formularza. Zwracając jednak false zamiast true (lub używając PreventDefault ()), zmienia sposób, w jaki przeglądarka obsługuje atrybut „required” elementu wejściowego. Wypróbuj sam: dodaj <code> required </code> do elementu wejściowego, przechwyć przesyłanie i zobacz, czy utracisz jego domyślne zachowanie.
Elisabeth
Wydaje się, że nie tracę domyślnego zachowania. Działa dobrze w Chrome. Aby mi pomóc, musisz podać błędny przykład.
kba
1
OK, oto formularz: <form method = "get" action = ""> <label for = "color"> Jaki jest twój ulubiony kolor? </label> <input type = "text" name = "color" placeholder = „niebieski” wymagany> <input id = "submit" type = "submit" value = "Submit"> </form>, a oto kod: function processForm (e) {var form = document.querySelector ("form"); for (var i = 0; i <form.childNodes.length; i ++) {var node = form.childNodes [i]; / * rób rzeczy z węzłami /} / return false; * /} Testowanie w operze. Odkomentuj ostatnią linię, wymagane nie powiodło się. (Przepraszamy, kod nie działa dobrze w komentarzach)
Elisabeth
6

Inną opcją obsługi wszystkich żądań, których użyłem w mojej praktyce w przypadkach, gdy onload nie może pomóc, jest obsługa przesyłania javascript, przesyłania html, żądań ajax. Ten kod należy dodać w górnej części elementu body, aby utworzyć odbiornik przed jakimkolwiek renderowaniem i przesłaniem formularza.

Na przykład ustawiłem ukryte pole na dowolny formularz na stronie podczas jego przesyłania, nawet jeśli dzieje się to przed załadowaniem strony.

//Handles jquery, dojo, etc. ajax requests
(function (send) {
    var token = $("meta[name='_csrf']").attr("content");
    var header = $("meta[name='_csrf_header']").attr("content");
    XMLHttpRequest.prototype.send = function (data) {
        if (isNotEmptyString(token) && isNotEmptyString(header)) {
            this.setRequestHeader(header, token);
        }
        send.call(this, data);
    };
})(XMLHttpRequest.prototype.send);


//Handles javascript submit
(function (submit) {
    HTMLFormElement.prototype.submit = function (data) {
        var token = $("meta[name='_csrf']").attr("content");
        var paramName = $("meta[name='_csrf_parameterName']").attr("content");
        $('<input>').attr({
            type: 'hidden',
            name: paramName,
            value: token
        }).appendTo(this);

        submit.call(this, data);
    };
})(HTMLFormElement.prototype.submit);


//Handles html submit
document.body.addEventListener('submit', function (event) {
    var token = $("meta[name='_csrf']").attr("content");
    var paramName = $("meta[name='_csrf_parameterName']").attr("content");
    $('<input>').attr({
        type: 'hidden',
        name: paramName,
        value: token
    }).appendTo(event.target);
}, false);
Vitaliy Borisok
źródło
2

Użyj odpowiedzi @Kristian Antonsen lub możesz użyć:

$('button').click(function() {
    preventDefault();
    captureForm();
});
rsplak
źródło
4
dla każdego, kto robi to 2,5 roku (lub więcej) później, musisz przekazać zdarzenie kliknięcia jako parametr do funkcji (jak in function(e)i calle.preventDefault()
digitaljoel.
Może być również przechwycony w zdarzeniu „wyślij” dla formularza, jeśli używane jest dane wejściowe [type = "submit"], co umieszcza Cię w kontekście formularza, a nie w kontekście przycisku. Wywołanie zwrotne zawsze będzie miało kontekst zdarzenia, więc niekoniecznie musisz podawać „e” jako argument, wystarczy odwołać się do „zdarzenia”.
augurone
1
Nie jest to zalecane, ponieważ przedłożenie może zostać wywołane przez naciśnięcie klawisza.
jhpratt