jQuery - предотвратить по умолчанию, затем продолжить по умолчанию

104

У меня есть форма, при отправке которой мне нужно выполнить дополнительную обработку, прежде чем она должна будет отправить форму. Я могу предотвратить отправку формы по умолчанию, затем выполнить дополнительную обработку (в основном это вызов Google Maps API и добавление нескольких скрытых полей в форму), а затем мне нужна форма для отправки.

Есть ли способ «предотвратить дефолт», а затем через некоторое время «продолжить дефолт»?

StackOverflowNewbie
источник
@FelixKling Вы имели в виду stackoverflow.com/questions/7610871/… ?
М. Мимпен,

Ответы:

54

Использовать jQuery.one()

Прикрепите обработчик к событию для элементов. Обработчик выполняется не более одного раза для каждого элемента для каждого типа события.

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

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

Использование oneпредотвращения также бесконечный цикл, потому что это настраиваемое submitсобытие отключается после первой отправки.

Аурел
источник
2
оно будет
любопытство
1
«Вероятно, вы столкнетесь с бесконечным циклом»
Мехрдад Хоссейн Нежад
Бесконечный цикл, функция должна быть .on, а не
.one
53

Когда вы привязываете .submit()событие к форме и делаете то, что хотите, перед возвратом (true), эти вещи происходят до фактической отправки.

Например:

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

Простой пример

Другой пример на jquery.com: http://api.jquery.com/submit/#entry-examples

Рон ван дер Хейден
источник
2
Вы говорите, что форма не будет отправлена ​​до тех пор, пока не будет выполнен весь код до "return true;" выписка выполняется?
Developarvin
2
Да, именно это и делает функция submit () .
Рон ван дер Хейден
8
Это не очень хороший пример, потому что он синхронный. Что, если мне нужно сделать асинхронный вызов? Итак, дело в следующем: «нажмите« Отправить »-> выполните асинхронные действия и не отправляйте форму -> в асинхронном обратном вызове заполните некоторые поля в форме -> отправьте форму из обратного вызова»
Крестный отец
1
А как насчет запуска асинхронного кода jQuery ?! Тоже будет работать?
Candlejack
это отлично работает для меня. Я использую его, чтобы контролировать вещи перед отправкой, а если что-то не так, я использую «return false». Я искал это решение целый день. большое спасибо.
livefreeor
26

Я бы просто сделал:

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

Вызовите preventDefaultсначала и используйте submit()функцию позже, если вам просто нужно отправить форму

бипен
источник
не включайте логику в обработчик событий щелчка. делегировать ответственность другим.
Рой Намир
27
Это предполагает, что пользователь обязательно нажмет кнопку. Что, если пользователь просто нажимает кнопку «Ввод» в форме? Это также отправит форму. Поэтому, вероятно, не стоит полагаться на нажатие кнопки отправки.
StackOverflowNewbie
я просто привел пример щелчка ... так как в вопросе не упоминалось никаких связанных кодов ....
bipen
2
В любом случае предоставленный вами фрагмент будет работать, только если пользователь нажмет кнопку. Формы работают не так. Есть другие предложения?
StackOverflowNewbie
привязать щелчок, предотвратить его значение по умолчанию и вызвать нажатие кнопки отправки
Candlejack
18

Таким образом вы создадите бесконечный цикл на своем JS. чтобы сделать лучший способ, вы можете использовать следующие

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.

Я надеюсь, что это помогает! Спасибо!

Joepreludian
источник
на самом деле лучший способ, вариант с функцией async - gist.github.com/BjornMelgaard/8ba0ee9d07c20dd8c8b3550c9df3e9ef
srghma
@bjornmelgaard Я должен помнить, что асинхронность нестандартна .
Валерио Бозз
6

Это, IMHO, наиболее универсальное и надежное решение (если ваши действия инициируются пользователем, например, «пользователь нажимает кнопку»):

  • при первом вызове обработчика проверьте, кто его инициировал:
    • если пользователь его задел - делайте свое дело, а затем запускайте его снова (если хотите) - программно
    • в противном случае - ничего не делать (= "продолжить по умолчанию")

В качестве примера обратите внимание на это элегантное решение для добавления «Вы уверены?» всплывающее окно для любой кнопки, просто украсив кнопку атрибутом. Мы условно продолжим поведение по умолчанию, если пользователь не откажется.

1. Давайте добавим к каждой кнопке, которую мы хотим, всплывающее окно с предупреждением: «Вы уверены?»:

<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. Прикрепите обработчики ко ВСЕМ таким кнопкам:

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

Вот и все.

игорлуди
источник
1
Отличный ответ! Я не знал, что вы можете передать дополнительный аргумент .trigger ()
Джеймс Хиббард
5
$('#myform').on('submit',function(event){
  // block form submit event
  event.preventDefault();

  // Do some stuff here
  ...

  // Continue the form submit
  event.currentTarget.submit();
});
Удаянта Уди Варнасурия
источник
3

С jQueryи небольшим вариантом ответа @Joepreludian выше:

Важные моменты, о которых следует помнить:

  • .one(...) вместо этого на .on(...) or .submit(...)
  • namedвместо функции, anonymous functionпоскольку мы будем ссылаться на нее внутри 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...
    }
});

Вы можете изменить значение allIsWellпеременной в ниже фрагменте кода , чтобы trueили falseдля тестирования функциональности:

$('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>

Удачи...

Акаши
источник
2

В чистом виде Javascript вы можете отправить форму после предотвращения дефолта.

Это происходит потому , что HTMLFormElement.submit() никогда не называетonSubmit() . Таким образом, мы полагаемся на эту странность спецификации, чтобы отправить форму, как если бы здесь нет настраиваемого обработчика onsubmit.

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

См. Эту скрипку для синхронного запроса.


Дождаться завершения асинхронного запроса так же просто:

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

Вы можете проверить мою скрипку для примера асинхронного запроса.


И если вы не обещаете:

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')
}

И вот эта просьба .

алайрок
источник
1

Вы можете использовать, e.preventDefault()который остановит текущую операцию.

чем ты можешь сделать$("#form").submit();

 $('#form').submit(function (e)
{
    return !!e.submit;
});
if(blabla...)
{...
}
else
{
    $('#form').submit(
    {
        submit: true
    });
}
Ройи Намир
источник
это очень сбивает меня с толку ... не будет ли это просто так?
dapidmini
1

«Внедрение валидации без цикла отправки»:

Я просто хочу проверить reCaptcha и некоторые другие вещи перед проверкой HTML5, поэтому я сделал что-то вроде этого (функция проверки возвращает true или false):

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

   });
});
Деннис Хайден
источник