如何让不显眼的 jquery 远程验证器执行异步..?
在 MVC3 应用程序中,使用 jquery 不显眼的验证以及带有 [远程] 验证器的视图/模型:我试图在远程验证期间以及将有效表单提交到服务器时禁用提交按钮并显示等待图标。我以为我已经搞定了,直到我在 IE8 中尝试了它。
问题是,当表单无效时,GC 和 FF 不会触发表单的提交事件,因此我只是在此事件期间禁用了提交按钮。然而,当表单无效时,IE8 会触发此事件,导致用户永远无法再次单击它。 (IE8 不提交表单,但事件被触发。)
我尝试将一个函数附加到提交按钮的单击事件。在那里,我禁用了提交按钮,显示了等待图标,并得到了以下结果:
$('[data-app-form-submit-button="true"]').live('click', function (e) {
var form = $(this).parents('form');
var icon = form.find('[data-app-form-submitting-icon="true"]');
icon.show();
$(this).attr('disabled', 'disabled');
$.ajaxSetup({ async: false });
var isValid = form.valid();
$.ajaxSetup({ async: true });
alert(isValid);
});
问题是,ajax 设置调用并没有真正关闭异步。如果我将其移出单击功能,它会执行此操作,但随后它会禁用所有内容的异步。相反,页面会立即发出“true”警报,这是通过在远程验证操作方法上设置断点进行测试的。
有什么想法吗?
附加说明:
我忘了提及,在 IE8 中,仅当相关文本框未通过客户端上可能发生的验证时才会触发提交事件。例如,如果必需的或正则表达式失败,则将触发 Submit()。对于远程验证操作方法,不会触发它。但是,一旦客户端验证失败,后续的远程验证也会触发 IE8 提交事件。
对 Russ Cam 的回应(评论 #1)
以下是视图模型中的相关代码:
public class SignUpForm : IValidatableObject
{
[DataType(DataType.EmailAddress)]
[Display(Name = "Email Address")]
[Required(ErrorMessage = "Email Address is required.")]
[RegularExpression(@"^(email regex here)$",
ErrorMessage = "This is not a valid email address.")]
[Remote("Validate", "ControllerName", "AreaName", HttpMethod = "POST")]
public string EmailAddress { get; set; }
public IEnumerable<ValidationResult> Validate(
ValidationContext validationContext)
{
我很高兴您让我查看渲染的
<form action="/post-action-method" method="post" novalidate="novalidate">
...
<input class="text-box single-line" data-app-focus="true" data-val="true"
data-val-regex="This is not a valid email address."
data-val-regex-pattern="^(email regex here)$"
data-val-remote="&#39;Email Address&#39; is invalid."
data-val-remote-additionalfields="*.EmailAddress"
data-val-remote-type="POST"
data-val-remote-url="/validate-action-method"
data-val-required="Email Address is required."
id="EmailAddress" name="EmailAddress" type="text" value="">
...
<input type="submit" value="Submit this form"
data-app-form-submit-button="true" />
直到现在我才看到 novalidate="novalidate" 属性。这是 cshtml 文件中的样子:
@using (Html.BeginForm())
{
@Html.EditorForModel()
@Html.AntiForgeryToken("assault")
}
我还使用防伪令牌,如果这有什么不同的话。谢谢。
In an MVC3 app, using jquery unobtrusive validation, and a view/model with a [Remote] validator: I am trying to disable the submit button and display a wait icon during remote validation, and when a valid form is submitted to the server. I thought I had it nailed until I tried it in IE8.
The problem was, GC and FF were not firing the form's submit event when the form was invalid, so I just disabled the submit button during this event. However IE8 is firing this event when the form is invalid, causing the user to never be able to click it again. (IE8 does not submit the form, but the event is fired.)
I tried attaching a function to the submit button's click event. In there, I disabled the submit button, showed the wait icon, and had this:
$('[data-app-form-submit-button="true"]').live('click', function (e) {
var form = $(this).parents('form');
var icon = form.find('[data-app-form-submitting-icon="true"]');
icon.show();
$(this).attr('disabled', 'disabled');
$.ajaxSetup({ async: false });
var isValid = form.valid();
$.ajaxSetup({ async: true });
alert(isValid);
});
The problem is, the ajax setup call is not really turning off async. It does if I move it out of the click function, but then it disables async for everything. Instead, the page alerts "true" immediately, tested by setting a breakpoint on the remote validation action method.
Any ideas?
Additional Note:
I forgot to mention, in IE8, the submit event is only being fired when the text box in question fails a validation that can happen on the client. For example, if it fails required or regex, submit() is fired. For the remote validation action method, it is not fired. However, as soon as it fails a client validation, subsequent remote validations also trigger the IE8 submit event.
Response to Russ Cam (comment #1)
Here is the relevant code in the viewmodel:
public class SignUpForm : IValidatableObject
{
[DataType(DataType.EmailAddress)]
[Display(Name = "Email Address")]
[Required(ErrorMessage = "Email Address is required.")]
[RegularExpression(@"^(email regex here)$",
ErrorMessage = "This is not a valid email address.")]
[Remote("Validate", "ControllerName", "AreaName", HttpMethod = "POST")]
public string EmailAddress { get; set; }
public IEnumerable<ValidationResult> Validate(
ValidationContext validationContext)
{
I'm glad you had me look at the rendered <form>
. The form tag and input elements look like this:
<form action="/post-action-method" method="post" novalidate="novalidate">
...
<input class="text-box single-line" data-app-focus="true" data-val="true"
data-val-regex="This is not a valid email address."
data-val-regex-pattern="^(email regex here)$"
data-val-remote="'Email Address' is invalid."
data-val-remote-additionalfields="*.EmailAddress"
data-val-remote-type="POST"
data-val-remote-url="/validate-action-method"
data-val-required="Email Address is required."
id="EmailAddress" name="EmailAddress" type="text" value="">
...
<input type="submit" value="Submit this form"
data-app-form-submit-button="true" />
I never saw the novalidate="novalidate" attribute until now. Here is what it looks like in the cshtml file:
@using (Html.BeginForm())
{
@Html.EditorForModel()
@Html.AntiForgeryToken("assault")
}
I am also using anti-forgery token, if that makes a difference. Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
这有点老套,但我建议尝试以下方法。
首先,使用
display="none"
隐藏提交按钮,并显示您自己的“提交”按钮,该按钮运行上面的脚本。其次,在您的页面中,添加一个标志 var [
var remotePending = false;
] 和一个用于setInterval
调用的变量 [var IntervalPending;
] ,并在您的脚本中将该标志设置为 true,然后使用intervalPending = setInterval('remoteCheck()', 200); 调用以下函数,
这将允许您等待待处理的完成远程验证,然后正常进行。我还没有测试过,所以你可能需要尝试一下才能按你想要的方式工作。
It's kind of hacky, but I would suggest trying the following.
First, hide the submit button with
display="none"
, and show your own "submit" button, which runs your script above.Second, in your page, add a flag var [
var remotePending = false;
] and a variable for asetInterval
call [var intervalPending;
], and in your script, set the flag to true, then call the following function usingintervalPending = setInterval('remoteCheck()', 200);
This will allow you to wait for the completion of the pending remote validation, then proceed normally. I have not tested, so you may have to play around to get this working as you want.
我对此有点晚了,但我在尝试解决类似问题时偶然发现了这个问题。我也不想使用 Interval,所以我制定了一个不同的解决方案,并认为可能值得在这里为其他人详细介绍。
最后我决定重写 jQuery 验证器 startRequest 和 stopRequest 方法以添加我自己的逻辑。执行我自己的逻辑后,我只需调用旧的验证器方法。
为了实现我的目的,我想做的就是简单地将“正在加载”CSS 类添加到相邻的验证消息字段,以显示正在加载的 gif,但您可以轻松扩展它以启用/禁用按钮等。
I'm a bit late to the table with this, but I stumbled across this question while trying to solve a similar problem. I too didn't want to use Interval, so I cooked up a different solution and thought it might be worth detailing here for others.
In the end I decided to override the jQuery validator startRequest and stopRequest methods in order to add my own logic. After executing my own logic I simply call the old validator methods.
All I wanted to do for my purposes was simply add a 'loading' css class to an adjacent validation message field in order to show a loading gif, but you could easily extend this to enable/disable a button, etc.
昨晚我发现自己对此感到困惑,在尝试了各种方法之后,我最终得到了辅导员的进化。由于辅导员不能直接开箱即用,我想我应该分享它以防止其他人遇到同样的头痛。它不像我想要的那样“干净”的解决方案(我真的很讨厌使用间隔)。但似乎就足够了。
I found myself puzzling over this last night and after trying various approaches I ended up with an evolution of counsellorbens. Since counsellorbens didn't work straight out of the box I thought I'd share it to prevent others having the same headache. It's not as "clean" a solution as I would like (I really hate using intervals). But it seems to suffice.
我最终解决了这个问题,但是按钮禁用/等待图像显示仅在存在有效的提交表单时才会发生。不过没关系,因为多个无效表单提交是幂等的,用户可以随意点击。 (此外,远程验证操作方法会根据其参数值进行缓存。)
这也有点 hacky,但是当我不使用 setTimeout 时,提交操作永远不会触发无效处理程序。
I ended up solving this, but the button disable / wait image show only happen when there is a valid submitted form. It's okay though, since multiple invalid form submissions are idempotent, the user can click as much as they want. (Also, the remote validation action method is cached against its parameter values.)
This is a little hacky too, but when I didn't use setTimeout, the submit action was never firing the invalid handler.
我经历了所有的方法,一切都很好,但没有任何效果。
然后我检查模型(类或DTO)项目的System.Web.Mvc版本,并且View的项目存在版本差异。我将两者更新到相同的版本,它对我有用。
我检查 html 生成丢失
data-val-remote-additionalfields=".电子邮件"
例如,我正在检查它们。
I went through all the approaches, all were fine but nothing worked me.
Then I check the version of System.Web.Mvc of model(class or DTO) project and and View's Project there was version difference. I update the both to same version and it worked for me.
I check the html generate was missing
data-val-remote-additionalfields=".Email"
e.g I was checking them.