jQuery - wyłącz domyślne, a następnie kontynuuj domyślne

104

Mam formularz, który po przesłaniu wymaga dodatkowej obróbki przed wysłaniem formularza. Mogę zapobiec domyślnemu zachowaniu przesyłania formularza, a następnie wykonać dodatkowe przetwarzanie (w zasadzie jest to wywołanie Google Maps API i dodanie kilku ukrytych pól do formularza) - a następnie potrzebuję formularza do przesłania.

Czy istnieje sposób, aby „zapobiec domyślnemu”, a następnie w pewnym momencie „kontynuować domyślne”?

StackOverflowNewbie
źródło
@FelixKling Czy chodziło Ci o stackoverflow.com/questions/7610871/… ?
M. Mimpen,

Odpowiedzi:

53

Kiedy łączysz .submit()zdarzenie z formularzem i robisz to, co chcesz zrobić przed zwróceniem (prawda), te rzeczy mają miejsce przed faktycznym przesłaniem.

Na przykład:

$('form').submit(function(){
    alert('I do something before the actual submission');
    return true;
});

Prosty przykład

Inny przykład na jquery.com: http://api.jquery.com/submit/#entry-examples

Ron van der Heijden
źródło
2
czy mówisz, że formularz nie zostanie przesłany, dopóki cały kod przed „return true”; instrukcja jest wykonywana?
developarvin
2
Tak, dokładnie to robi funkcja submit () .
Ron van der Heijden
8
To nie jest dobry przykład, ponieważ jest synchroniczny. A jeśli rzecz, którą muszę zrobić, to połączenie asynchroniczne? Tak więc sprawa wygląda następująco: „kliknij wyślij -> wykonaj czynności asynchroniczne i nie wysyłaj formularza -> w wywołaniu zwrotnym asynchronicznym wypełnij niektóre pola formularza -> wyślij formularz z oddzwonienia”
Ojciec chrzestny
1
A co z uruchomieniem asynchronicznego kodu jQuery ?! Czy też zadziała?
blask świec,
to działa świetnie dla mnie. Używam go do kontrolowania rzeczy przed przesłaniem, a jeśli coś jest nie tak, używam „return false”. Szukałem tego rozwiązania od dnia. wielkie dzięki.
livefreeor
53

Posługiwać się jQuery.one()

Dołącz procedurę obsługi do zdarzenia dla elementów. Procedura obsługi jest wykonywana co najwyżej raz na element na typ zdarzenia

$('form').one('submit', function(e) {
    e.preventDefault();
    // do your things ...

    // and when you done:
    $(this).submit();
});

Użycie funkcji Prevent onerównież nieskończonej pętli, ponieważ submitzdarzenie niestandardowe jest wyłączane po pierwszym przesłaniu.

Aurel
źródło
2
prześle po ponownym kliknięciu :(
ciekawość
Prawdopodobnie
zmierzysz się
Nieskończona pętla, funkcja powinna być .on nie
.one
26

Po prostu zrobiłbym:

 $('#submiteButtonID').click(function(e){
     e.preventDefault();
     //do your stuff.
     $('#formId').submit();
 });

Zadzwoń preventDefaultnajpierw, a submit()później użyj funkcji, jeśli potrzebujesz tylko przesłać formularz

bipen
źródło
nie używaj logiki w module obsługi zdarzeń kliknięcia. delegować odpowiedzialność na innych.
Royi Namir
27
Zakłada się, że na pewno kliknie przycisk. Co się stanie, jeśli użytkownik po prostu kliknie przycisk „Enter” z poziomu formularza? Spowoduje to również przesłanie formularza. Więc prawdopodobnie nie jest dobrym pomysłem poleganie na kliknięciu przycisku przesyłania.
StackOverflowNewbie,
podałem
2
W każdym razie podany fragment kodu będzie działał tylko wtedy, gdy użytkownik kliknie przycisk. Nie tak działają formularze. Jakieś inne sugestie?
StackOverflowNewbie
powiązać kliknięcie, uniemożliwić jego domyślne ustawienie i wywołać kliknięcie przycisku przesyłania
Candlejack
18

Używając w ten sposób, wykonasz nieskończoną pętlę na swoim JS. aby zrobić lepszy sposób, możesz użyć następujących

var on_submit_function = function(evt){
    evt.preventDefault(); //The form wouln't be submitted Yet.
    (...yourcode...)

    $(this).off('submit', on_submit_function); //It will remove this handle and will submit the form again if it's all ok.
    $(this).submit();
}

$('form').on('submit', on_submit_function); //Registering on submit.

Mam nadzieję, że to pomoże! Dzięki!

Joepreludian
źródło
właściwie najlepszy sposób, wariacja z funkcją async - gist.github.com/BjornMelgaard/8ba0ee9d07c20dd8c8b3550c9df3e9ef
srghma
@bjornmelgaard Muszę pamiętać, że asynchronizacja jest niestandardowa .
Valerio Bozz,
6

To jest, IMHO, najbardziej ogólne i niezawodne rozwiązanie (jeśli twoje działania są wyzwalane przez użytkownika, np. „Użytkownik klika przycisk”):

  • przy pierwszym wywołaniu programu obsługi sprawdź, kto go uruchomił:
    • jeśli użytkownik go przejął - zrób swoje, a następnie uruchom go ponownie (jeśli chcesz) - programowo
    • w przeciwnym razie - nic nie rób (= "kontynuuj domyślnie")

Jako przykład zwróć uwagę na to eleganckie rozwiązanie dodawania „Czy na pewno?” wyskakujące okienko do dowolnego przycisku, po prostu dekorując przycisk atrybutem. Będziemy warunkowo kontynuować domyślne zachowanie, jeśli użytkownik nie zrezygnuje.

1. Dodajmy do każdego przycisku, który ma mieć wyskakujące okienko „Czy na pewno”, tekst ostrzeżenia:

<button class="btn btn-success-outline float-right" type="submit"  ays_text="You will lose any unsaved changes... Do you want to continue?"                >Do something dangerous</button>

2. Dołącz programy obsługi do WSZYSTKICH takich przycisków:

$('button[ays_text]').click(function (e, from) {
    if (from == null) {  // user clicked it!
        var btn = $(this);
        e.preventDefault();
        if (confirm() == true) {
            btn.trigger('click', ['your-app-name-here-or-anything-that-is-not-null']);
        }
    }
    // otherwise - do nothing, ie continue default
});

Otóż ​​to.

igorludi
źródło
1
Świetna odpowiedź! Nie wiedziałem, że możesz przekazać dodatkowy argument do .trigger ()
James Hibbard
5
$('#myform').on('submit',function(event){
  // block form submit event
  event.preventDefault();

  // Do some stuff here
  ...

  // Continue the form submit
  event.currentTarget.submit();
});
Udayantha Udy Warnasuriya
źródło
3

Z jQuerymałą odmianą odpowiedzi @ Joepreludian powyżej:

Ważne kwestie, o których należy pamiętać:

  • .one(...) zamiast na .on(...) or .submit(...)
  • namedfunkcja zamiast, anonymous functionponieważ będziemy odnosić się do niej w ramach callback.

$('form#my-form').one('submit', function myFormSubmitCallback(evt) {
    evt.stopPropagation();
    evt.preventDefault();
    var $this = $(this);
    if (allIsWell) {
        $this.submit(); // submit the form and it will not re-enter the callback because we have worked with .one(...)
    } else {
        $this.one('submit', myFormSubmitCallback); // lets get into the callback 'one' more time...
    }
});

Możesz zmienić wartość allIsWellzmiennej w poniższym fragmencie na truelub w falsecelu przetestowania funkcjonalności:

$('form#my-form').one('submit', function myFormSubmitCallback(evt){
  evt.stopPropagation();
  evt.preventDefault();
  var $this = $(this);
  var allIsWell = $('#allIsWell').get(0).checked;
  if(allIsWell) {
    $this.submit();
  } else {
    $this.one('submit', myFormSubmitCallback);
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form action="/" id="my-form">
  <input name="./fname" value="John" />
  <input name="./lname" value="Smith" />
  <input type="submit" value="Lets Do This!" />
  <br>
  <label>
    <input type="checkbox" value="true" id="allIsWell" />
    All Is Well
  </label>
</form>

Powodzenia...

Akash
źródło
2

Formularz można przesłać w czystym języku Javascript po zapobieżeniu domyślnemu.

To dlatego, że HTMLFormElement.submit() nigdy nie zwracaonSubmit() . Więc polegamy na tej dziwności specyfikacji, aby przesłać formularz tak, jakby nie miał tutaj niestandardowej procedury obsługi onsubmit.

var submitHandler = (event) => {
  event.preventDefault()
  console.log('You should only see this once')
  document.getElementById('formId').submit()
}

Zobacz te skrzypce, aby uzyskać synchroniczne żądanie.


Czekanie na zakończenie żądania asynchronicznego jest równie łatwe:

var submitHandler = (event) => {
  event.preventDefault()
  console.log('before')
  setTimeout(function() {
    console.log('done')
    document.getElementById('formId').submit()
  }, 1400);
  console.log('after')
}

Możesz sprawdzić moje skrzypce, aby zobaczyć przykład żądania asynchronicznego.


A jeśli nie masz obietnic:

var submitHandler = (event) => {
  event.preventDefault()
  console.log('Before')
    new Promise((res, rej) => {
      setTimeout(function() {
        console.log('done')
        res()
      }, 1400);
    }).then(() => {
      document.getElementById('bob').submit()
    })
  console.log('After')
}

A oto ta prośba .

alairock
źródło
1

Możesz użyć, e.preventDefault()który zatrzyma bieżącą operację.

niż możesz zrobić$("#form").submit();

 $('#form').submit(function (e)
{
    return !!e.submit;
});
if(blabla...)
{...
}
else
{
    $('#form').submit(
    {
        submit: true
    });
}
Royi Namir
źródło
to jest dla mnie bardzo zagmatwane… czy to nie będzie się kręcić w kółko?
dapidmini
1

„Wstrzyknięcie walidacyjne bez zapętlenia przesyłania”:

Chcę tylko sprawdzić reCaptcha i kilka innych rzeczy przed walidacją HTML5, więc zrobiłem coś takiego (funkcja walidacji zwraca prawdę lub fałsz):

$(document).ready(function(){
   var application_form = $('form#application-form');

   application_form.on('submit',function(e){

        if(application_form_extra_validation()===true){
           return true;
        }

        e.preventDefault();

   });
});
Dennis Heiden
źródło