我有求职网站。用户填写表格并从PC中选择CV(简历)文件,然后点击“发送”按钮。这将调用ajaxSubmit()函数,该函数执行本地验证(从下面的代码中删除),如果可以,则执行AJAX文件上传。服务器端进行进一步的验证,并以JSON返回SUCCESS或ERROR(加上错误文本)。
当用户点击“发送”按钮时,我打开一个模态#apply_working_modal,它仅显示一个微调图标。在ajax.done上,我关闭#apply_working_modal,如果有错误,请将其放在模式#apply_errors_modal的主体上并打开它。
我第一次尝试,故意出现错误,它按所述方式工作。如果我再次尝试,但错误仍然存在,则会显示#apply_working_modal,并且直到我手动单击X或将其移开时,它才会关闭。
这似乎是一个时间问题,因为在发生错误后重新提交时,CV文件已在服务器上,因此JSON很快返回。实际上,如果我稍微限制一下网络,我就能使其正常工作。
我尝试了等待模态事件的各种方法,还尝试setTimeout()来延迟#apply_errors_modal的打开
function ajaxSubmit(whichForm){
$("#apply_working_modal").modal("show");
console.log('showing apply_working_modal');
var applyRequest =$.ajax({
url: postUrl,
etc: etc
});
applyRequest.done(function( data, textStatus, jqXHR ) {
console.log(data);
$("#apply_working_modal").modal("hide");
console.log("hiding #apply_working_modal ");
if (data.STATUS =='SUCCESS') {
// validation OK at server
}
else {// validation error at server
$('#apply_working_modal').on('hidden.bs.modal', function () {
$("#apply_errors_modal_body").html(data.ErrorText);
$("#apply_errors_modal").modal("show");
console.log("on hidden of #apply_working_modal");
})
}
});
}
这是好/坏测试的控制台输出:
//Expected behaviour
15:58:45.981 myscript.js:179 showing apply_working_modal
// 10 seconds pass while server uploads file and returns errors in JSON
15:58:56.696 myscript.js:206 {STATUS: "ERROR", ErrorText: "* The Comments are too short."}
15:58:56.700 myscript.js:217 hiding #apply_working_modal
15:58:56.998 myscript.js:236 on hidden of #apply_working_modal
// Problem behaviour
15:59:26.704 myscript.js:179 showing apply_working_modal
15:59:26.723 myscript.js:206 {STATUS: "ERROR", ErrorText: "* The Comments are too short."}
15:59:26.724 myscript.js:217 hiding #apply_working_modal
// #apply_working_modal never gets hidden, have to manually close it
// manual dismiss of modal after waitinf 13 secs ....
15:59:38.525 myscript.js:236 on hidden of #apply_working_modal
15:59:38.526 myscript.js:236 on hidden of #apply_working_modal
// error modal shown but logged many times?
HTML:
<!-- apply working (spinner while sending cv) -->
<div id="apply_working_modal" class="modal fade" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title"><i class="fa fa-hourglass-end"></i><span class="sr-only">Loading...</span> Sending your CV</h4>
<button type="button" class="close" data-dismiss="modal"><i class="fa fa-times-circle-o" aria-hidden="true"></i></button>
</div>
<div class="modal-body text-center">
<i class="fa fa-spinner fa-spin fa-5x fa-fw"></i><span class="sr-only">Loading...</span>
</div>
<div class="modal-footer">
</div>
</div>
</div>
</div>
<!-- apply errors modal-->
<div id="apply_errors_modal" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<h4 style='color:#cc0000;' class="modal-title"><i class="fa fa-exclamation-triangle" aria-hidden="true"></i> There were errors!</h4>
<button type="button" class="close" data-dismiss="modal"><i class="fa fa-times-circle-o" aria-hidden="true"></i></button>
</div>
<div id="apply_errors_modal_body" class="modal-body">
</div>
<div class="modal-footer">
<button data-dismiss="modal" type="button" style="float:left;" class="btn btn-outline-info">Cancel</button>
</div>
</div>
</div>
</div>
根据下面的答案/评论进行更新。
为了清楚起见,在发布问题时我简化了ajax请求,因为我不认为这是原因-在我的代码中,我将“ etc:etc”用作ajax参数,这表明我简化了代码。我确实在使用cache:false。下面的完整调用(在代码中较早地设置了postUrl):
var applyRequest =$.ajax({
url: postUrl,
data: postData,
type: "POST",
xhr: function() { // Custom XMLHttpRequest
var myXhr = $.ajaxSettings.xhr();
if(myXhr.upload){ // Check if upload property exists
myXhr.upload.addEventListener('progress',progressHandler, false); // For handling the progress of the upload
}
return myXhr;
},
enctype: 'multipart/form-data',
cache: false,
processData: false, // tell jQuery not to process the data (reqd for use with FormData)
contentType: false, // tell jQuery not to set contentType
dataType: "json"
});
答案 0 :(得分:4)
您是对的时间安排是正确的,如果背景动画尚未完成,模态将不会被隐藏。参见https://getbootstrap.com/docs/4.1/getting-started/javascript/#asynchronous-functions-and-transitions
异步方法和转换
所有API方法都是异步并开始过渡。他们 过渡开始后立即返回到呼叫者,但之前 结束。另外,在转换组件上的方法调用 将被忽略。
—以上引用来自https://getbootstrap.com/docs/4.1/components/modal/#events
(更新后的答案-我删除了cache: false
的内容。)
所以尝试隐藏模态,如下所示:
// Wait for the modal to be made fully visible, where CSS transitions have completed.
$('#apply_working_modal').one('shown.bs.modal', function(){
$(this).modal("hide");
});
See the description of the shown.bs.modal
for more information.
或像这样使用setTimeout()
:
setTimeout(function(){
$('#apply_working_modal').modal("hide");
}, 1000);
(再次更新)以上(shown.bs.modal
)有效,但在我的测试中,仅当cache
为true
时。很可能是因为shown.bs.modal
在触发.done()
之前已经被触发。因此,尝试以这种方式进行操作:
(另一个更新)抱歉,我本人忘了使用.one()
..其次,我将其与setTimeout()
方法结合使用,以使模式隐藏是“太早了..
(2018年8月15日,supsth) 我添加了丢失的部分-$("#apply_working_modal").modal("show");
(正好在此答案中;感谢@ KevinSol指出了它出来!)。
function ajaxSubmit(whichForm){
var modal_shown = false;
$('#apply_working_modal').one('shown.bs.modal', function(){
modal_shown = true;
});
$("#apply_working_modal").modal("show");
...
applyRequest.done(function( data, textStatus, jqXHR ) {
...
// If the modal has been *fully* visible, simply hides it.
if (modal_shown) {
$('#apply_working_modal').modal("hide");
// Else, wait until it's fully visible, and then hides it.
} else {
$('#apply_working_modal').one('shown.bs.modal', function(){
// Wait a few ms before we hide the modal.
setTimeout(function(){
$('#apply_working_modal').modal("hide");
}, 100);
modal_shown = true;
});
}
...
});
}
这是针对shown.bs.modal
事件的 a 更新后的demo 和针对setTimeout()
方法的another demo
此处应使用.one()
而不是.on()
:
//$('#apply_working_modal').on('hidden.bs.modal' // before
$('#apply_working_modal').one('hidden.bs.modal' // correct
以防止事件处理程序被多次触发: