【发布时间】:2017-08-18 02:28:07
【问题描述】:
我在这里陷入了一个非常奇怪的境地。解释起来很复杂,但我会尽力而为。
问题的详细解释:
在每次顶部导航单击(绿色甜甜圈/圆圈)或下一步按钮时,我必须提交表单,如果它存在并且有效。如果无效, form.valid() 会触发验证错误并返回 false 将停止任何进一步的传播。在我注意到一个不是很持久的奇怪行为之前,这个设置工作得很好。具体来说,我的第三个选项卡上的表单数据量很大。当我点击下一个按钮时,它实际上应该经过相同的过程:检查现有表单,如果有效,然后提交。 Submit 调用 POST 操作方法,并在 post 完成时获取下一个选项卡的视图。它像这样工作 5/10 次,但有时 GET 在 POST 之前执行,这会导致下一页加载不完整的数据。当我设置断点进行调试时,我看到在当前选项卡的 POST 之前执行下一个选项卡的 GET。
用户界面解释:
我有一个 UI,顶部有 4 个导航 <a> 按钮 - 在中心始终有一个表单 - 在底部我有上一个和下一个按钮。
在 MVC 中使用 Ajax.BeginForm 构造表单
对于顶部的每个导航链接 <a> 元素,我有一个 JavaScript 函数
var LoadTabs = function (e, arg) {
// This is to validate a form if one of the top links is clicked and form has incomplete fields...
if (arg !== "prev" && arg !== "next") {
if (!window.ValidateForm(false)) return false;
}
var url = $(this).attr('data'); // this contains link to a GET action method
if (typeof url != "undefined") {
$.ajax(url, { context: { param: arg } }).done(function (data) {
$('#partialViewContainer').html(data);
});
}
}
上面的这个函数绑定到页面加载时的每个顶部链接。
$('.navLinks').on('click', LoadTabs);
我的下一个和上一个按钮基本上会触发点击事件,即LoadTabs 函数。
$('button').on('click', function () {
if (this.id === "btnMoveToNextTab") {
if (!window.ValidateForm(true)) return false;
$.ajax({
url: url,
context: { param: 'next' },
method: "GET",
data: data,
success: function(response) {
if (typeof response == 'object') {
if (response.moveAhead) {
MoveNext();
}
} else {
$('#mainView').html(response);
}
ScrollUp(0);
}
});
}
if (this.id === "btnMoveToPreviousTab") {
MoveBack();
}
return false;
});
MoveNext() Implementation is as below:
function MoveNext() {
var listItem = $('#progressbarInd > .active').next('li');
listItem.find('.navLink').trigger('click', ['next']);
ScrollUp(0);
}
问题是,由于某些原因,当导航链接 3 处于活动状态并且我点击下一步按钮时 - 而不是首先通过 form.submit() 发布表单 - 导航 4 被触发 - 因此导航 4 的 GET 在表单之前运行导航 3 的 POST。
我的 ValidateForm 方法基本上只是检查表单是否存在并且是否有效然后提交,否则返回 false。如下:
function ValidateForm(submit) {
var form = $('form');
// if form doesn't exist on the page - return true and continue
if (typeof form[0] === "undefined") return true;
// now check for any validation errors
if (submit) {
if (!$(form).valid()) {
return false;
} else {
$(form).submit();
}
}
else {
return true;
}
return true;
}
我的猜测是 form.submit 确实会被触发,但由于提交需要更长的时间才能完成,它会继续按钮 onclick 事件中的下一个代码块。
我首先认为这是一个服务器端问题,因为在 POST 中我通过几个循环保存了大量数据,并且任何处理繁重的代码块我都有那部分
var saveTask = Task.Factory.StartNew(() => ControllerHelper.SomeMethod(db, model)); Task.WaitAll(saveTask);
WaitAll 将等待并暂停执行,直到 SomeMethod 完成执行。我不确定如何在 JavaScript 中锁定进程并等待它完成执行。因为我认为如果我能以某种方式将 form.submit() 锁定在 ValidateForm 中,直到其完成处理..也许通过回调方法......
如果有人能给我指明正确的方向,我将不胜感激。如果您需要更多信息,请告诉我,我很乐意提供!
【问题讨论】:
-
你为什么使用
Ajax.BeginForm()是你使用$.ajax()。但问题是 ajax 是异步的。当您调用ValidateForm()并且它有效时,将对 POST 方法进行 ajax 调用。然后代码进入下一个$.ajax()调用您的GET 方法。它们同时发生,无法保证哪个会先完成。 -
在非常简单的 ajax 表单提交和更新页面响应(从操作方法返回的部分视图)之前,我们没有这些验证逻辑。感谢您指出这一点。是的,我也这么认为...我只是想了解是否有办法停止/暂停代码运行直到 POST 完成...
-
不清楚“下一个”、“上一个”和“导航链接”按钮的用途。如果这是您必须按顺序完成每个步骤时的某种“向导”,那么您的表格 1-3 应该只有一个“下一步”提交按钮,而表格 4 应该有一个“完成”按钮(以及“栏”在顶部应该只是一个视觉指示器)。在任何情况下,您都应该处理表单
.submit()事件,检查isvalid()(如果是则取消),然后创建一个 $.post()`,该方法应该返回适当的局部视图以更新 DOM。 -
如果表格可以按任何顺序完成,那么用户当然应该能够跳转到他们想要的任何表格,即使他们已经开始完成之前的表格(也许你只是显示一个在允许他们转到另一个表格之前确认)
-
不幸的是,这就是应用程序 UI 结构的方式......我无法改变它。它实际上不仅仅是顶部的 4 个选项卡。顶部有 4 个主选项卡(大声笑),每个主选项卡有 4 个子选项卡(NavLinks - 圆圈/甜甜圈)。表单并不存在于每一页上。下一个/上一个是主视图的一部分,表格在我附加的那张照片中,那是一个局部视图容器,其中视图被动态加载......并且没有任何表格不能以任何顺序完成 - 至少在每个其中已填满,然后用户可以在应用程序中跳转。但是第一次 - 这是他们必须遵守的严格命令,
标签: javascript c# jquery asp.net-mvc asp.net-mvc-5