如果在Ajax表单中使用,jQuery不显眼validation会忽略提交按钮上的“取消”类

我正在尝试使用实现可选的客户端validation

  • ASP.NET MVC 4,
  • 不引人注目的jQueryvalidation,
  • 不引人注目的ajax

这很好用

下面的图片显示了我对可选的客户端validation的意思:我的表单上唯一一个字段应该包含电子邮件,因此附加了一个电子邮件validation器。

在此处输入图像描述

现在我们点击保存。 由于我们的文本“name @ doamin”不是有效的电子邮件,因此会显示validation摘要。 与validation摘要一起,我们取消隐藏“无论如何”保存按钮。

在此处输入图像描述

第二个按钮是一个普通的提交按钮,只有class="cancel" 。 这指示jQuery.validate.js脚本在使用此按钮提交时跳过validation。

以下是视图的代码段:

 @using (Html.BeginForm()) { 
*
@Html.ValidationSummary(false, "Still errors:")
}

一切正常。

问题

如果我切换到Ajax表单,第二个提交按钮 – “仍然保存”按预期停止工作。 它的行为与正常行为相同,并且在validation成功之前阻止提交。

以下是“ajaxified”视图的代码段:

 @using (Ajax.BeginForm("Edit", new { id = "0" }, new AjaxOptions { HttpMethod = "POST", InsertionMode = InsertionMode.Replace, UpdateTargetId = "ajaxSection", })) { 
*
@Html.ValidationSummary(false, "Still errors:")
}

我调试了jQuery.validation.js以找出有什么不同,但失败了。

Qustion

任何修复或解决问题并让ajax表单按预期运行的想法都是受欢迎的。


附录

要进行客户端validation是绝对必要的。 服务器端validation不是一个选项。 除了更高的流量(此示例是简化 – 真实表单包含更多字段)和延迟之外,服务器端validation还有一件事情不会做:客户端validation器突出显示丢失焦点上的错误字段。 这意味着只要您切换到下一个字段,您就会收到反馈。

这是微软不显眼的ajax脚本的一个已知限制。 你可以修改它来修复bug。 所以在jquery.unobtrusive-ajax.js脚本中替换第144行的以下内容:

 $(form).data(data_click, name ? [{ name: name, value: evt.target.value }] : []); 

有:

 $(form).data(data_click, name ? [{ name: name, value: evt.target.value, className: evt.target.className }] : []); 

此外,我们将类名传递给处理程序,以便它可以决定是否应该触发客户端validation。 目前,无论点击哪个按钮,它始终会触发validation。 现在在第154行,我们修改了以下测试:

 if (!validate(this)) { 

有:

 if (clickInfo[0].className != 'cancel' && !validate(this)) { 

这样,如果使用带有类名取消的提交按钮来提交表单,则不再触发客户端validation。 另一种可能性是刮掉jquery.unobtrusive-ajax.js脚本并用标准的Html.BeginForm替换你的Ajax.BeginForm ,你可以使用普通的旧jQuery不引人注意地使用AJAXify。

最后,我找到了一个解决方案,它本身并不引人注目

  // restore behavior of .cancel from jquery validate to allow submit button // to automatically bypass all jquery validation $(document).on('click', 'input[type=image].cancel,input[type=submit].cancel', function (evt) { // find parent form, cancel validation and submit it // cancelSubmit just prevents jQuery validation from kicking in $(this).closest('form').validate().cancelSubmit = true; $(this).closest('form').submit(); return false; }); 

注意:如果首先尝试它似乎不起作用 – 请确保您没有往返服务器并刷新页面时出错。 您将不得不通过其他方式绕过服务器端的validation – 这只是允许提交表单而不必将.ignore属性添加到表单中的所有内容。

(如果使用按钮,可能需要向选择器添加按钮)

如果不需要Unobtrusivevalidation,请将其禁用并在服务器端执行所有检查。

您可以检查服务器端的“提交”按钮的值,然后根据该值继续:

为两个提交输入添加name属性:

   

更新您的操作以获取string btnSubmit 。 如果您有模型,可以将其放入模型中。

 [HttpPost] public ActionResult Edit(string emailfield, string btnSubmit) { switch (btnSubmit) { case "Save": if(ModelState.IsValid) { // Save email } break; case "Save anyway": // Save email return RedirectToAction("Success"); break; } // ModelState is not valid // whatever logic to re display the view return View(model); } 

UPDATE

我知道客户端validation简化了工作,但是如果你无法弄清楚Ajax有什么问题(我不熟悉它在输入时打字=“取消”时的行为),你可以写一个会validation的脚本服务器端未聚焦的输入:

 $('input[type=text]').blur(function(){ $.ajax({ url: '/ControllerName/ValidateInput', data: { inputName: $(this).val() }, success: function(data) { //if there is a validation error, display it }, error: function(){ alert('Error'); } }); }); 

现在,您需要创建一个将对输入进行validation的操作:

 public ActionResult ValidateInput(string inputName) { bool isValid = true; string errorMessage = ""; switch (inputName) { case "password" // do password validation if(!inputIsValid) { isValid = false; errorMessage = "password is invalid"; } break; case "email" // do email validation if(!inputIsValid) { isValid = false; errorMessage = "email is invalid"; } break; } return Json(new { inputIsValid = isValid, message = errorMessage }); } 

这有点麻烦,但正如我所说,如果你不弄清楚客户端validation,它可以工作。


UPDATE

不知道为什么我没有想到这个…而不是依靠class="cancel"你可以这样做:

给你的“反正”提交输入ID:

  

然后有一个这样的脚本:

 $('#submitAyway').click(function(evt) { evt.preventDefault(); $('form').submit(); }); 

我没有对此进行测试,但从理论上讲,这应该在不validation的情况下提交表单。 你可能仍然需要服务器端validation,就像我在第一个例子中所示。