我在 ASP.NET Core Razor Pages 页面上有一个表单。如果我向表单添加提交按钮 (
type="submit"
),表单将按预期正常发布。
如果我将提交按钮更改为常规按钮 (
type="button"
) 并为该按钮添加一个调用 .trigger('submit')
的处理程序,它也会按预期正常发布。
$('#myButton').on('click', function () {
$('#myForm').trigger('submit');
});
但是,如果我更改处理程序进行如下所示的
$ajax()
调用,并从 done
处理程序中触发表单提交,则会收到 400 错误。
$('#myButton').on('click', function () {
var $form = $(this).closest('form');
$.ajax({
type: 'GET',
url: '?handler=ValidateProductTransfer',
contentType: 'application/json',
dataType: 'json',
data: { ... },
})
.done(function (response) {
if (response.isSuccess)
$form.trigger('submit'); // <----- FAILS w/400 error!
else
alert(response.error);
})
.fail(function (response) {
alert(response.responseText);
})
});
我可以通过延迟表单提交来解决上述问题。
.done(function (response) {
if (response.isSuccess)
setTimeout(function () {
$form.trigger('submit'); // <----- OK
}, 300);
else
alert(response.error);
})
显然,在
$ajax().done
处理程序中触发表单提交时存在问题。但我不明白为什么,或者为什么会导致 400 错误。
谁能解释一下这里发生了什么?以及如何解决这个问题而不施加延迟,如果延迟不够的话可能会失败?
如果有帮助,这是我实际的 JavaScript 处理程序。
$('#product-transfer-submit').on('click', function () {
disablePopup(true);
var $form = $(this).closest('form');
var $modal = $('#transfer-product-modal');
var $activeTab = $modal.find('a.nav-link.active');
var targetType = $activeTab.data('type');
var targetId = $modal.find($activeTab.attr('href') + ' :input').val();
$modal.find('#TargetType').val(targetType);
$.ajax({
type: 'GET',
url: '?handler=ValidateProductTransfer',
contentType: 'application/json',
dataType: 'json',
data: {
'sourceId': $modal.find('#SourceId').val(),
'targetType': targetType,
'targetId': targetId,
'productId': $modal.find('#ProductId').val()
},
})
.done(function (response) {
if (response.isSuccess)
//setTimeout(function () {
$form.trigger('submit');
//}, 300);
else
alert(response.error);
})
.fail(function (response) {
alert(response.responseText);
})
.always(function (response) {
disablePopup(false);
});
});
function disablePopup(disable) {
$("#transfer-product-modal :input").prop("disabled", disable);
$("#transfer-product-modal a").prop("disabled", disable);
}
这是我在浏览器中呈现的完整表单。
<div id="transfer-product-modal" class="modal show" tabindex="-1" role="dialog" aria-modal="true" style="display: block;">
<form method="post" action="/Transloading/Ships?handler=ProductTransfer" novalidate="novalidate">
<input type="hidden" data-val="true" data-val-required="The SourceId field is required." id="SourceId" name="SourceId" value="2">
<input type="hidden" data-val="true" data-val-required="The TargetType field is required." id="TargetType" name="TargetType" value="Ship">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Ship 2 : Transfer Product To</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<ul class="nav nav-tabs">
<li class="nav-item">
<a href="#railcar-content" data-bs-toggle="tab" aria-expanded="false" class="nav-link" data-type="railcar">
<span class="d-block d-sm-none"><img src="/images/mdi/calendar.svg" title="Railcar"></span>
<span class="d-none d-sm-block">Railcar</span>
</a>
</li>
<li class="nav-item">
<a href="#storage-content" data-bs-toggle="tab" aria-expanded="false" class="nav-link" data-type="storage">
<span class="d-block d-sm-none"><img src="/images/mdi/calendar.svg" title="Storage"></span>
<span class="d-none d-sm-block">Storage</span>
</a>
</li>
<li class="nav-item">
<a href="#ship-content" data-bs-toggle="tab" aria-expanded="false" class="nav-link active" data-type="ship">
<span class="d-block d-sm-none"><img src="/images/mdi/calendar.svg" title="Ships"></span>
<span class="d-none d-sm-block">Ship</span>
</a>
</li>
</ul>
<div class="tab-content mt-3 mb-3">
<div id="railcar-content" class="tab-pane">
<div class="row">
<div class="col-md-12">
<div class="form-group">
<label class="control-label" for="RailcarId">Railcar</label>
<select class="form-select" data-val="true" data-val-required="The Railcar field is required." id="RailcarId" name="RailcarId"><option value="36167">AOKX482582</option>
<option value="36400">AOKX491641</option>
<option value="36399">AOKX497959</option>
<option value="36240">CBFX305181</option>
<option value="36245">TOPX311252</option>
<option value="36193">TOPX311288</option>
<option value="36244">TOPX311390</option>
</select>
<span class="text-danger field-validation-valid" data-valmsg-for="RailcarId" data-valmsg-replace="true"></span>
</div>
</div>
</div>
</div>
<div id="storage-content" class="tab-pane">
<div class="row">
<div class="col-md-12">
<div class="form-group">
<label class="control-label" for="StorageId">Storage</label>
<select class="form-select" data-val="true" data-val-required="The Storage field is required." id="StorageId" name="StorageId"><option value="15">Test Storage (100 Mesh)</option>
</select>
<span class="text-danger field-validation-valid" data-valmsg-for="StorageId" data-valmsg-replace="true"></span>
</div>
</div>
</div>
</div>
<div id="ship-content" class="tab-pane active">
<div class="row">
<div class="col-md-12">
<div class="form-group">
<label class="control-label" for="ShipId">Ship</label>
<select class="form-select" data-val="true" data-val-required="The Ship field is required." id="ShipId" name="ShipId"><option value="1">Ship 1</option>
<option value="2">Ship 2</option>
</select>
<span class="text-danger field-validation-valid" data-valmsg-for="ShipId" data-valmsg-replace="true"></span>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="mb-3">
<label class="control-label" for="ProductId">Product</label>
<select class="form-select" data-val="true" data-val-required="The Product field is required." id="ProductId" name="ProductId"><option value="1">100 Mesh</option><option value="18">Butane</option><option value="19">Diesel</option><option value="40">Propane</option></select>
<span class="text-danger field-validation-valid" data-valmsg-for="ProductId" data-valmsg-replace="true"></span>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group mb-3">
<label class="control-label" for="Quantity">Quantity</label>
<input class="form-control" type="text" data-val="true" data-val-number="The field Quantity must be a number." data-val-range="Quantity must be a positive number" data-val-range-max="1000000000" data-val-range-min="0.1" data-val-required="The Quantity field is required." id="Quantity" name="Quantity" value="0">
<span class="text-danger field-validation-valid" data-valmsg-for="Quantity" data-valmsg-replace="true"></span>
</div>
</div>
<div class="col-md-6">
<div class="form-group mb-3">
<label class="control-label" for="Timestamp">Timestamp</label>
<input class="form-control" type="datetime-local" data-val="true" data-val-required="The Timestamp field is required." id="Timestamp" name="Timestamp" value="0001-01-01T00:00"><input name="__Invariant" type="hidden" value="Timestamp">
<span class="text-danger field-validation-valid" data-valmsg-for="Timestamp" data-valmsg-replace="true"></span>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" data-val="true" data-val-required="The Mark source as empty field is required." id="MarkAsEmpty" name="MarkAsEmpty" value="true">
<label class=" form-check-label" for="MarkAsEmpty">Mark source as empty</label>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" id="product-transfer-submit" class="btn btn-success">Transfer</button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
</div>
</div>
</div>
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8BlcV1FRqxZOunKbIAf54ZLanzQR8IEs7WCpxJ-3rTLTtnUwgcrJW0eL-Tl3Z_3exdKwVNmoPzo3m644U1W1i1nwO3iJDvZVW6EXTKkrdGHZJPh_QkKWU_6k5wGPNDpDzPwVOAK8p7CmxDE2QzacCwz3rUcnjpXhyrhWhup0xq7e6n50j0vA3TBlBKR2bxfOzA"><input name="MarkAsEmpty" type="hidden" value="false">
</form>
</div>
问题是您的
disablePopup()
函数禁用了表单中的所有输入。
禁用的输入不包含在提交的数据中。超时起作用的原因是它为您的
.always()
回调提供了重新启用输入的机会。
您可以更改延迟回调的顺序,以确保在处理成功或失败之前重新启用输入...
$.ajax({
url: "",
method: "GET",
data: {
targetType,
targetId,
handler: "ValidateProductTransfer",
sourceId: $modal.find("#SourceId").val(),
productId: $modal.find("#ProductId").val(),
},
dataType: "json",
})
.always(() => { // 👈 register "always" first
disablePopup(false);
})
.done(({ isSuccess, error }) => {
if (isSuccess) {
$form.trigger("submit");
} else {
alert(error);
}
})
.fail(({ responseText }) => {
alert(responseText);
});
注意一些细微的变化: