ASP.NET MVC - Как предотвратить двойной щелчок при отправке с jquery.validate.unobtrusive lib - PullRequest
14 голосов
/ 27 декабря 2010

Мне нужно избегать поведения отправки двойного клика.Я использую проверку клиента с помощью ненавязчивой библиотеки.У меня есть следующий код для избежания двойного щелчка:

jQuery.fn.preventDoubleSubmit = function () {
         var alreadySubmitted = false;
         return jQuery(this).submit(function () {

             if (alreadySubmitted)
                 return false;
             else {
                 alreadySubmitted = true;
             }
         });
     };

     jQuery('form').preventDoubleSubmit();

К сожалению, если моя форма имеет несколько допустимых полей (например, обязательное поле), приведенный выше код все еще запускается, следовательно, даже еслиЯ исправляю любые ошибки в форме, я не смогу отправить их снова.

Как я могу запустить код двойного щелчка после успешной проверки?

Ответы [ 9 ]

17 голосов
/ 06 января 2011

Вы также можете использовать событие JQuery One .

Я обнаружил, что могу быстро обойти большинство охранников от двойных щелчков.Использование одного события - единственный верный способ убедиться, что событие запускается только один раз.Я не думаю, что этот метод будет работать "из коробки" с тегом input type = submit.Вместо этого вы можете просто использовать кнопку ввода type = button или .button () * JQueryUI *) .

$("#submitButton").one("click", function(event) {
   $('#theForm').submit();
});

Если вам нужно повторно подключить событие кошибка проверки (или другое обстоятельство), я рекомендую вам создать функцию для обработчика событий.В этом примере функция не обязательна, поскольку все, что делает обработчик событий, - это отправка формы, но в более сложных сценариях вы можете избежать повторения.

function submitClick(event) {
   $('#theForm').submit();
}

$("#submitButton").one('click', function(event) {
   submitClick(event);
});

// This handler will re-wire the event when the form is invalid.
$('#theForm').submit(function(event) {
   if (!$(this).valid()) {
      event.preventDefault();
      $('#submitButton').one('click', function(event) { submitClick(event); });
   }
});

Очевидно, вы можете добавить сюда код отключенияесли вы хотите дать отзыв пользователю, что кнопка больше не работает.Одним из замечательных побочных эффектов использования события One является то, что вам не нужно отключать кнопку, вы можете использовать собственный стиль.

function submitClick(event) {
   $('#submitButton').addClass('disabledButton');
   $('#theForm').submit();
}

$("#submitButton").one('click', function(event) {
   submitClick(event);
});

// This handler will re-wire the event when the form is invalid.
$('#theForm').submit(function(event) {
   if (!$(this).valid()) {
      event.preventDefault();
      $('#submitButton').one('click', function(event) { submitClick(event); });
      $('#submitButton').removeClass('disabledButton');
   }
});

JQuery One Event: http://api.jquery.com/one/

8 голосов
/ 28 декабря 2010

Я решил это с помощью следующего кода:

var tryNumber = 0;
 jQuery('input[type=submit]').click(function (event) {
     var self = $(this);

     if (self.closest('form').valid()) {
         if (tryNumber > 0) {
             tryNumber++;
             alert('Your form has been already submited. wait please');
             return false;
         }
         else {
             tryNumber++;
         }
     };
 });

ПРИМЕЧАНИЕ: Вы также можете заменить строку:

return false;

, для:

self.attr('disabled', true);

НО, если вы используете название кнопок отправки на вашем контроллере для дополнительной логики, они будут отправлены как нулевые.(вы можете использовать дополнительное скрытое поле, чтобы зарядить их перед отправкой)

все, надеюсь, это поможет

Родриго

РЕДАКТИРОВАТЬ: Благодаря этим сообщениям: jqueryновичок: совмещать проверку и скрытие кнопки отправки

3 голосов
/ 08 сентября 2012

На основе популярного ответа Райана П. Я создал следующее общее решение, которое также работает с моей формой ajax.

украсил вашу пользовательскую кнопку отправки следующим классом:

<button type="button" class="one-click-submit-button">Submit</button>

Добавьте следующее в ваш файл javascript:

function OneClickSubmitButton() {
    $('.one-click-submit-button').each(function () {
        var $theButton = $(this);
        var $theForm = $theButton.closest('form');

        //hide the button and submit the form
        function tieButtonToForm() {
            $theButton.one('click', function () {
                $theButton.hide();
                $theForm.submit();
            });
        }

        tieButtonToForm();

        // This handler will re-wire the event when the form is invalid.
        $theForm.submit(function (event) {
            if (!$(this).valid()) {
                $theButton.show();
                event.preventDefault();
                tieButtonToForm();
            }
        });
    });
}

OneClickSubmitButton();

, так как это форма ajax, мы хотим перезагрузить обработчики, если мы не пройдем проверку сервера.

function MyForm_OnSuccess() {
    if (true if your form passed validation logic) {
        //do something since your form submitted successfully
    } else { //validation failed on server
        OneClickSubmitButton(); //reinitialize the button logic
    }
}

Очевидно, еслиу вас нет ajax-форм, вы можете опустить весь бизнес-функции OneClickSubmitButton и запустить $('.one-click-submit-button').each(... напрямую.

3 голосов
/ 07 октября 2011

Почему бы просто не использовать:

function disableButtons() {
    var form = $(this);
    var btns = $("input:submit", form);

    if (!form.valid()) {
        // allow user to correct validation errors and re-submit
        btns.removeAttr("disabled");
    } else {
        btns.attr("disabled", "disabled");
    }
}

, чтобы отключить кнопки и активировать их с помощью:

$("form").bind("submit", disableButtons);
2 голосов
/ 21 мая 2014
 $('form').submit(function () {
 $('input[type="submit"]', this).attr('disabled', 'disabled');
   });
1 голос
/ 22 июля 2014

Я использую другой подход к этому. Не для связи с событием нажатия кнопки, а для события отправки формы. Работает как брелок для предотвращения одновременной отправки нескольких форм.

function initFormsToPreventSimultaneousSubmits(selector) {
    if (!selector) {
        selector = 'form'; // No selector supplied, apply to all forms on the page
    }

    // Make sure all forms that conform to selector are marked as not submitting
    $(selector).each(function()
    {
        var $form = $(this);
        $form.data('submitting', false);
    });

    // Attach to submit event of all forms that conform to selector
    $(selector).off('submit').on('submit', function (e) {
        var $form = $(this);

        if (!$form.valid || $form.valid()) { // Make sure to only process when the form is valid or jquery validation is not used
            if ($form.data('submitting')) {
                // form is already submitting. Classic case of double click on one of the submit buttons of the form. Stop the submit
                e.preventDefault();
                return false;
            } else {
                // All ok, mark the form as submitting and let the form perform the submit
                $form.data('submitting', true);
                return true;
            }
        }
    });
}

Когда документ готов, я вызываю initFormsToPreventSimchronousSubmits () для инициализации всех форм на странице.

Единственное, что следует помнить, это то, что когда вы используете форму сообщения ajax, вы вызываете initFormsToPreventSimchronousSubmits ('# formId') для события OnComplete настроек AjaxOptions. Потому что в противном случае форма все равно будет помечена как отправляющая, когда это будет сделано. Когда используется «нормальная» форма сообщения, это не проблема.

1 голос
/ 18 октября 2011

У меня есть форма, использующая ненавязчивую проверку MVC3, и модель представления с [RemoteAttribute]. Мне кажется, что событие отправки формы срабатывает только после того, как вся проверка прошла успешно. Я в настоящее время использую это, и, кажется, работает:

<input type="submit" value="Submit the Form" 
    data-app-disable-on-submit="true" />

$('form').live('submit', function() {
    $(this).find('input[type="submit"][data-app-disable-on-submit="true"]')
                .attr('disabled', 'disabled');
})

;

Я установил точки останова как для метода действия удаленной проверки атрибута, так и для метода действия HttpPost. При первом нажатии кнопки отправки достигается точка останова в методе действия проверки. На данный момент кнопка все еще включена. Я могу щелкнуть по нему несколько раз, и после возобновления метода проверки HttpPost срабатывает только один раз. Когда нажата HttpPost, кнопка отправки отключена.

Обновление

Правильно, ты Алекс. Таким образом, обновленная версия выше будет выглядеть так:

$('form').on('submit', function() {
    $(this).find('input[type="submit"][data-app-disable-on-submit="true"]')
                .attr('disabled', 'disabled');
})
0 голосов
/ 12 октября 2015

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

Я только что создал глобальную переменную javascript, которую я переключал, когда моя функция выполнялась во время критической секции. Это удерживало последующие вызовы функций от повторного выполнения того же раздела.

 var criticalSection = false;

 SomeOnClickEventFired = function () {
      if (!criticalSection)
      {
            criticalSection = true;
            //Ajax Time
            criticalSection = false;
      }
 }
0 голосов
/ 19 февраля 2014

Расширяет ответы на Alex и Ryan P для учета ситуаций, когда проверка JQuery может отсутствовать и когда несколько кнопок отправки существуют в одной форме.

oneClickSubmitButton = function () {
    $('input[type=submit], button[type=submit], input[type=image]').each(function () {
        var $theButton = $(this);
        var $theForm = $theButton.closest('form');

        //hide the button and submit the form
        function tieButtonToForm() {
            $theButton.one('click', function () {
                $theButton.addClass('ui-state-disabled');
            });
        }

        tieButtonToForm();

        $theForm.submit(function (event) {
            // Only proceed for the clicked button
            if (!$theButton.hasClass("ui-state-disabled"))
                return;

            // If jQuery Validation is not present or the form is valid, the form is valid
            if (!$theForm.valid || $theForm.valid())
                return;

            // Re-wire the event
            $theButton.removeClass('ui-state-disabled');
            event.preventDefault();
            tieButtonToForm();
        });
    });
};
...