ASP.NET MVC - 如何防止使用 jquery.validate.unobtrusive lib 双击提交?

发布于 2024-10-09 07:21:48 字数 521 浏览 2 评论 0原文

我需要避免双击提交行为。我正在将客户端验证与不显眼的库一起使用。我有以下代码来避免双重点击:

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

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

     jQuery('form').preventDoubleSubmit();

不幸的是,如果我的表单有一些有效字段(例如必填字段),上面的代码仍然会被触发,因此,即使我纠正了表单上的任何错误,我将无法再次提交。

验证成功后如何触发双击代码?

I need to avoid the double click submitting behavior. I'm using the client validation with the unobtrusive library. I have the following code for avoiding the double clic:

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

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

     jQuery('form').preventDoubleSubmit();

Unfortunately, if my form has some validable fields (for example, a required field), the code above is still being fired, hence, even if I correct any mistakes on the form, I won't be able to submit it again.

How can I fire the double click code after the validation has been succesfully done?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

此刻的回忆 2024-10-16 07:21:48

您还可以使用 JQuery One 事件

我发现我可以通过快速双击来绕过大多数双击的防御。使用单一事件是确保事件仅触发一次的唯一正确方法。我不认为这种技术可以“开箱即用”地使用输入类型=提交标签。相反,您可以简单地使用输入 type=button 或 JQueryUI 的 .button()

$("#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 事件: http://api.jquery.com/one/

You can also use the JQuery One event.

I have found that I could get past most guards against double-clicks by double-clicking fast. Using the one event is the only true way to make sure the event is only fired once. I don't think this technique will work "out of the box" with an input type=submit tag. Instead, you can simply use an input type=button or JQueryUI's .button().

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

If you need to re-wire the event on a validation error (or other circumstance), I recommend that you create a function for the event handler. The function isn't necessary in this example because all the event handler does is submit the form, but in more complicated scenarios you may want to avoid repeating yourself.

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

You could obviously add the disabling code here if you wanted to give feedback to the user that the button doesn't work anymore. One great side-effect of using the One event is that you don't actually have to make the button disabled, you can use a style of your own.

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/

孤君无依 2024-10-16 07:21:48

我用以下代码解决了这个问题:

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

但是,如果您使用控制器上的提交按钮的名称来获取额外的逻辑,它们将被作为 null 发送。 (您可以在提交之前使用额外的隐藏字段向他们收费)

就是这样,希望它能帮助

罗德里戈

编辑:感谢这些帖子:
jquery新手:将验证与隐藏提交按钮结合起来

I solved it with the following code:

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++;
         }
     };
 });

NOTE: You can also replace the:

return false;

line, for:

self.attr('disabled', true);

BUT, if you use the name of your submit buttons on your controller for extra logic, they will be sent as null. (you can use an additional hidden field to charge them before submitting)

that's it, hope it helps

Rodrigo

EDIT: Thanks to these posts:
jquery newbie: combine validate with hidding submit button

ぶ宁プ宁ぶ 2024-10-16 07:21:48

为什么不直接使用:

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

Why not just use:

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");
    }
}

to disable your buttons and activate it using:

$("form").bind("submit", disableButtons);
剩余の解释 2024-10-16 07:21:48

基于 Ryan P 的热门答案,我创建了以下通用解决方案,该解决方案也适用于我的 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(... 直接。

Based on Ryan P's popular answer I created the following generic solution that also works with my ajax form.

decorate your custom submit button with the following class:

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

Add the following to your javascript file:

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

since this is an ajax form we want to reload the handlers if we fail server validation.

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

Obviously if you don't have ajax forms you can omit the whole OneClickSubmitButton function business and run $('.one-click-submit-button').each(... directly.

2024-10-16 07:21:48

我有一个使用 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');
})

I have a form that uses MVC3 unobtrusive validation, and a viewmodel with a [RemoteAttribute].
It looks to me like the form's submit event only fires after all validation has passed. I'm currently using this, and it seems to work:

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

;

I set breakpoints on both the remote attribute validation action method and the HttpPost action method. Clicking the submit button the first time hits the breakpoint on the validation action method. At this point, the button is still enabled. I can click it multiple times, and after resuming the validation method, the HttpPost is hit only once. When the HttpPost is hit, the submit button is disabled.

Update

Right you are Alex. So an updated version of the above would look like this:

$('form').on('submit', function() {
    $(this).find('input[type="submit"][data-app-disable-on-submit="true"]')
                .attr('disabled', 'disabled');
})
笑脸一如从前 2024-10-16 07:21:48
 $('form').submit(function () {
 $('input[type="submit"]', this).attr('disabled', 'disabled');
   });
 $('form').submit(function () {
 $('input[type="submit"]', this).attr('disabled', 'disabled');
   });
花开柳相依 2024-10-16 07:21:48

我对此使用不同的方法。不连接到按钮的单击事件,而是连接到表单的提交事件。就像一个咒语一样,可以防止同时提交多个表单。

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

文档准备好后,我调用 initFormsToPreventSimultaneousSubmits() 来初始化页面上的所有表单。

唯一要记住的是,当您使用 ajax 表单发布时,请在 AjaxOptions 设置的 OnComplete 事件上调用 initFormsToPreventSimultaneousSubmits('#formId') 。因为否则表单在完成后仍将被标记为已提交。当使用“正常”表单帖子时,这不是问题。

I use a different approach to this. Not wiring to the click event of the button, but to the submit event of the form. Works like a charm to prevent multiple simultaneous submits of forms.

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

On document ready i call initFormsToPreventSimultaneousSubmits() to init all forms on the page.

Only thing to remember is that when u use a ajax form post is to call the initFormsToPreventSimultaneousSubmits('#formId') on the OnComplete event of the AjaxOptions settings. Because otherwise the form will still be marked as submitting when its done. When a 'normal' form post is used this is not an issue.

半夏半凉 2024-10-16 07:21:48

扩展了 AlexRyan 的答案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();
        });
    });
};

Extends answers by Alex and Ryan P to accounts for situations where jQuery Validation might be missing and where multiple submit buttons exist in a single form.

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();
        });
    });
};
忆梦 2024-10-16 07:21:48

我能够用几行代码解决类似的问题。如果您不想“警告”用户双击并只是默默地忽略第二次单击,我更喜欢这样做。

我刚刚创建了一个全局 JavaScript 变量,当我的函数在关键部分执行时,我会切换该变量。这可以防止后续函数调用重新执行同一部分。

 var criticalSection = false;

 SomeOnClickEventFired = function () {
      if (!criticalSection)
      {
            criticalSection = true;
            //Ajax Time
            criticalSection = false;
      }
 }

I was able to fix a similar issue with a couple of lines of code. I prefer this if you don't want to "alert" to user that they double clicked and just silently ignore the second click.

I just made a global javascript variable that I toggled when my function was executing during a critical section. This kept subsequent function calls from re-executing the same section.

 var criticalSection = false;

 SomeOnClickEventFired = function () {
      if (!criticalSection)
      {
            criticalSection = true;
            //Ajax Time
            criticalSection = false;
      }
 }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文