jQuery:表单提交 - 多个事件处理程序

Posted

技术标签:

【中文标题】jQuery:表单提交 - 多个事件处理程序【英文标题】:jQuery: Form Submission - Multiple Event Handlers 【发布时间】:2020-03-01 13:39:35 【问题描述】:

目前我的项目中的 jQuery 表单提交存在一些问题。

我的项目包含一个通用 jQuery 代码,可防止表单重复提交(例如,有人多次单击“提交”按钮)。

//prevent multiple form submissions
jQuery.fn.preventDoubleSubmission = function () 
    $(document).on('submit', this, function (e) 
        let $form = $(this);
        if ($form.data('submitted') === true) 
            e.preventDefault();
         else 
            $form.data('submitted', true);
        
    );
    return this;
;


$(function () 
    $('form').preventDoubleSubmission();
);

此代码包含在每个页面中 - 因此每个表单都应该受到“保护”。

对于某些特定的表单,我需要在提交之前检查一些值 - 如果缺少某些值,则显示一个确认框(例如,您确定要提交没有值 X 的表单吗?)

代码如下:

$(document).on('submit', 'form[name="article"]', function (e) 
    e.preventDefault();
    let form = this;
    let $form = $(form);
    let $category = $form.find('select#article_category'); //get category

    if ($category.length && !$category.val())  //check if category is selected
        $.confirm( //jquery confirm plugin
            title: "Are you sure?",
            content: "Value X is missing - continue?",
            buttons: 
                confirm: 
                    action: function () 
                        $form.off('submit');
                        form.submit();
                    
                
            
        );
     else 
        $form.off('submit');
        form.submit();
    
);

所以基本上,如果用户尝试提交表单,但缺少值 X,首先会出现一个是/否弹出窗口 - 如果值存在,表单将立即提交。

问题: 当我想提交表单时,我调用$form.off('submit'); 删除事件处理程序,然后使用form.submit(); 提交。可悲的是,这也删除了我的 preventDoubleSubmission 事件处理程序,它允许再次提交双重提交。

有没有办法解决我的问题?谢谢

【问题讨论】:

你能把你的html也包括进来吗? 【参考方案1】:

下面是带有正确解决方案的代码 sn-p。您的原始方法存在多个问题,在 sn-p 下方突出显示。最好在不同的代码游乐场中运行这个 sn-p,其中使用 javascript 的操作可以工作,例如JSFiddle。

//prevent multiple form submissions
function submitOnce (e, $form) 
  alert('submitted = ' + $form.data('submitted'));
  if ($form.data('submitted') === true) 
    e.preventDefault();
    alert('Double-submission prevented!');
   else 
    $form.data('submitted', true);
    alert('Double-submission param saved');
  



$(document).on('submit', 'form[name="article"]', function (e) 
		let form = this;
    let $form = $(form);
    
    let $category = $form.find('select#article_category'); //get category

    if ($category.length && !$category.val())  //check if category is selected
    
      if ( confirm("Are you sure?") )
        submitOnce(e,$form);
      
      else 
      	e.preventDefault();
      
        
     else 
        submitOnce(e,$form);
    
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form name="article" action="javascript:alert('Form submitted!');">
  <select id="article_category" name="select1">
    <option></option>
    <option>option1</option>
    <option>option2</option>
  </select>
  <input type="submit" />
</form>

编辑:添加解释

如果您直接在表单元素上绑定“提交”事件处理程序,$form.off() 会起作用,但在这两种情况下,处理程序都会在文档上注册。

没有必要调用form.submit(),因为我们已经在提交处理程序中,因此提交已经被调用。我们只需要阻止提交继续。

最好只有一个提交处理程序,并在那里处理双重提交。

e.preventDefault(); 必须只在 else 子句中,用于未确认的情况和 submitOnce()。您在主处理程序的开头有它,但它在那里没有用,因为form.submit() 在内部再次被调用,并且此调用不会阻止默认值。

我的方法不是万无一失的,只是作为需要改变的示范。

【讨论】:

感谢您的回复。我喜欢您的解释-因为 +1,但是您的解决方案对我不起作用。您使用 javascript confirm 会暂停脚本,直到您按下是/否。我的confirm plugin 的行为并非如此,这意味着我的表单已立即提交,即使我的confirm 出现了。也许您可以提供另一种方法。谢谢【参考方案2】:

一种方法是使用带有点击事件的正常范围。单击它后,您可以禁用它(例如使用类),然后提交表单。这种方法允许您控制表单提交,而无需额外编码。

看这个例子:

$submitBtn = jQuery(".submit");
$form = jQuery("form[name='article']");

$submitBtn.on("click", function() 
  if (jQuery(this).hasClass("disabled"))
    return;

  let $category = $form.find('.name'); //get value

  if ($category.length && !$category.val())  //check if value is set
    $.confirm( //jquery confirm plugin
      title: "Are you sure ?",
      content: 'Value x is missing - continue ?',
      buttons: 
        confirm: 
          action: function() 
            $form.submit();
            $submitBtn.addClass("disabled");
          
        ,
        cancel: function() 
          //$.alert('canceled');
        
      
    );

    return;
  

  $submitBtn.addClass("disabled");
  $form.submit();

);
form 
  border: 1px solid rgba(0, 0, 0, 0.1);
  padding: 1.5rem;
  display: flex;
  flex-direction: column;
  width: 200px;


form input 
  margin-bottom: 0.5rem;
  padding: 0.3rem;
  border-radius: 3px;
  border: 1px solid gray;


form .submit 
  padding: 0.3rem 1rem;
  cursor: pointer;
  border-radius: 3px;
  background-color: rgba(0, 0, 0, 0.1);
  text-align: center;
  transition: all 0.3s;


form .submit.disabled 
  opacity: 0.5;
  cursor: default;
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/jquery-confirm/3.3.2/jquery-confirm.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-confirm/3.3.4/jquery-confirm.min.js"></script>

<form action="" name='article'>
  First name:<br>
  <input type="text" name="firstname" value="My First Name" class='name'>
  <br> Last name:<br>
  <input type="text" name="lastname" value="My Last Name">
  <br><br>
  <span class='submit'>Submit</span>
</form>

【讨论】:

感谢您的回复。这可以按照你的建议工作,但是我真的不想重写我已经拥有的每一个表单。纯 JS/jQuery 解决方案会更好地满足我的需求。然而很好的答案。谢谢【参考方案3】:

所以我终于想出了一个对我来说相对不错的解决方案。不过它很简单,我可能会坚持下去。

//form submission function
function submitForm(form) 
    let $form = $(form);
    let $submit = $form.find('button[type=submit]'); //find submit button

    $submit.attr('disabled', true); //disable button = prevent double submission
    form.submit(); //submit form


//submission for every form but not .form-confirm
$(document).on('submit', 'form:not(.form-confirm)', function (e) 
    e.preventDefault();
    submitForm(this); //call function
);

$(document).on('submit', 'form[name="article"]', function (e) 
    e.preventDefault();
    let form = this;
    let $form = $(form);

    let $category = $form.find('select#article_category'); //get category

    if ($category.length && !$category.val())  //check if category is selected
        $.confirm(
            title: "Are you sure?",
            content: "Value X is missing - continue?",
            buttons: 
                confirm: 
                    action: function () 
                        submitForm(form); //call function
                    
                
            
        );
     else 
        submitForm(form); //call function
    
);

那么它是如何工作的呢?

基本上我只是在提交后禁用提交按钮(=防止重复提交)。我在弹出窗口应显示的特定表单中添加了一个名为form-confirm 的类,因此一般规则在那里不起作用。 我总是使用preventDefault 并使用form.submit() 在我的代码中立即提交。

【讨论】:

以上是关于jQuery:表单提交 - 多个事件处理程序的主要内容,如果未能解决你的问题,请参考以下文章

如何在没有单独的单击事件处理程序的情况下处理多个表单提交 [关闭]

jQuery 提交事件处理程序只工作一次

jQuery同一标签多个相同事件 return语句 表单提交实例

jQuery 的 .on() 方法结合提交事件

jQuery:如何获取表单提交时点击了哪个按钮?

jQuery拦截表单提交到参数字符串