在 jQuery 完成修改表单中的值之前提交表单
Form is submitted before jQuery is finished modifying values in the form
这是我正在尝试做的事情:单击单选按钮时,我想更新表单中的一些值,只有在这些值更新后,才提交整个表单。我遇到的问题是,在更新值之前提交了表单。
这是我当前的(非工作)实现:
<div class="btn-group" data-toggle="buttons">
<label id="label_radio_2_78" class="btn btn-info btn-sm checkbox-padding ">
<input onchange="update_transaction(78)" id="radio_2_78" name="ledger_id" value="2" type="radio">
BR
</label>
<label id="label_radio_3_78" class="active">
<input onchange="switch_ledgers(78, 3)" id="radio_3_78" checked="checked" name="ledger_id" value="3" type="radio">
HP
</label>
</div>
function switch_ledgers(transactionId, ledgerId)
{
deactivate_radio(transactionId, ledgerId).done
(
update_transaction(transactionId)
);
}
//checks if the clicked radio buttion is active, if so it unchecks it.
function deactivate_radio(transactionId, ledgerId)
{
var cb = $('#radio_' + ledgerId + '_' + transactionId + ':checked');
var r = $.Deferred();
if(cb)
{
cb.prop('checked', false);
$('#label_radio_' + ledgerId + '_' + transactionId).removeClass('active');
}
return r.resolve();
}
//Submits the form, this function gets called too quickly
function update_transaction(transactionId)
{
var form = $("#transaction_" + transactionId);
$.ajax({
type: form.attr('method'),
data: form.serialize(),
url: form.attr('action')
}).done(function()
{
update_balance();
update_total_balance();
});
}
我希望我已经足够清楚地说明了我要做什么。
谢谢!
在我看来,问题是当你实际上试图将它作为 .done()
:
的回调函数传递时,你执行了 update_transaction()
function switch_ledgers(transactionId, ledgerId)
{
deactivate_radio(transactionId, ledgerId).done
(
update_transaction(transactionId)
);
}
应该是
function switch_ledgers(transactionId, ledgerId)
{
deactivate_radio(transactionId, ledgerId).done
(
function() {
update_transaction(transactionId)
}
);
}
如果您没有将参数传递给 update_transaction()
,您可以直接使用
deactivate_radio(transactionId, ledgerId).done(update_transaction); //No ()
但现在您必须将调用包装在匿名函数中以避免立即执行 update_transaction()
。
您似乎是在第一个输入元素的 onchange 事件中直接调用 update_transaction()。
你不应该在更改事件中调用 switch_ledgers() 吗?
例如:
<input onchange="switch_ledgers(78)" id="radio_2_78" name="ledger_id" value="2" type="radio">
直截了当,您只需要修复 switch_ledgers()
以免立即调用 update_transaction()
(Peter Herdenborg 的回答)。
更进一步,您可以(并且应该):
- 从
deactivate_radio()
中清除 deferred/promise,这是完全同步的。
- 在 javascript 中附加事件处理程序,而不是作为 HTML 属性。
- 利用 jQuery 的强大功能遍历 DOM.
,避免繁琐的 ID
一定有一千种编写代码的方法 - 这里是一种:
HTML
清除 ID 和 onchange=
属性以支持 data-
属性
<div class="btn-group" data-toggle="buttons" data-transactionId="78">
<label class="btn btn-info btn-sm checkbox-padding">
<input data-changeHandler="update_transaction" name="ledger_id" value="2" type="radio"> BR
</label>
<label class="active">
<input data-changeHandler="switch_ledgers" checked="checked" name="ledger_id" value="3" type="radio"> HP
</label>
</div>
Javascript
// Attach a generalised change handler to the radio buttons,
// braching out to a specific function as specified by
// the button's `data-changeHandler` property.
$(".btn-group input[type='radio']").on('change', function () {
changeHandlers[$(this).data('changeHandler')](this);
});
// Branching above is made simple by specifying
// the specific change handlers as properties of an object.
var changeHandlers = {
'switch_ledgers': function(button) {
$(button).filter(':checked').prop('checked', false).closest("label").removeClass('active');
changeHandlers.update_transaction(button);
},
'update_transaction': function(button) {
var transactionId = $(button).closest(".btn-group").data('transactionId'),
form = $("#transaction_" + transactionId);
$.ajax({
type: form.attr('method'),
data: form.serialize(),
url: form.attr('action')
}).done(function() {
update_balance();
update_total_balance();
});
}
}
现在,将其他按钮组中的HTML修改为与上面相同的模式。
这是我正在尝试做的事情:单击单选按钮时,我想更新表单中的一些值,只有在这些值更新后,才提交整个表单。我遇到的问题是,在更新值之前提交了表单。
这是我当前的(非工作)实现:
<div class="btn-group" data-toggle="buttons">
<label id="label_radio_2_78" class="btn btn-info btn-sm checkbox-padding ">
<input onchange="update_transaction(78)" id="radio_2_78" name="ledger_id" value="2" type="radio">
BR
</label>
<label id="label_radio_3_78" class="active">
<input onchange="switch_ledgers(78, 3)" id="radio_3_78" checked="checked" name="ledger_id" value="3" type="radio">
HP
</label>
</div>
function switch_ledgers(transactionId, ledgerId)
{
deactivate_radio(transactionId, ledgerId).done
(
update_transaction(transactionId)
);
}
//checks if the clicked radio buttion is active, if so it unchecks it.
function deactivate_radio(transactionId, ledgerId)
{
var cb = $('#radio_' + ledgerId + '_' + transactionId + ':checked');
var r = $.Deferred();
if(cb)
{
cb.prop('checked', false);
$('#label_radio_' + ledgerId + '_' + transactionId).removeClass('active');
}
return r.resolve();
}
//Submits the form, this function gets called too quickly
function update_transaction(transactionId)
{
var form = $("#transaction_" + transactionId);
$.ajax({
type: form.attr('method'),
data: form.serialize(),
url: form.attr('action')
}).done(function()
{
update_balance();
update_total_balance();
});
}
我希望我已经足够清楚地说明了我要做什么。
谢谢!
在我看来,问题是当你实际上试图将它作为 .done()
:
update_transaction()
function switch_ledgers(transactionId, ledgerId)
{
deactivate_radio(transactionId, ledgerId).done
(
update_transaction(transactionId)
);
}
应该是
function switch_ledgers(transactionId, ledgerId)
{
deactivate_radio(transactionId, ledgerId).done
(
function() {
update_transaction(transactionId)
}
);
}
如果您没有将参数传递给 update_transaction()
,您可以直接使用
deactivate_radio(transactionId, ledgerId).done(update_transaction); //No ()
但现在您必须将调用包装在匿名函数中以避免立即执行 update_transaction()
。
您似乎是在第一个输入元素的 onchange 事件中直接调用 update_transaction()。
你不应该在更改事件中调用 switch_ledgers() 吗?
例如:
<input onchange="switch_ledgers(78)" id="radio_2_78" name="ledger_id" value="2" type="radio">
直截了当,您只需要修复 switch_ledgers()
以免立即调用 update_transaction()
(Peter Herdenborg 的回答)。
更进一步,您可以(并且应该):
- 从
deactivate_radio()
中清除 deferred/promise,这是完全同步的。 - 在 javascript 中附加事件处理程序,而不是作为 HTML 属性。
- 利用 jQuery 的强大功能遍历 DOM. ,避免繁琐的 ID
一定有一千种编写代码的方法 - 这里是一种:
HTML
清除 ID 和 onchange=
属性以支持 data-
属性
<div class="btn-group" data-toggle="buttons" data-transactionId="78">
<label class="btn btn-info btn-sm checkbox-padding">
<input data-changeHandler="update_transaction" name="ledger_id" value="2" type="radio"> BR
</label>
<label class="active">
<input data-changeHandler="switch_ledgers" checked="checked" name="ledger_id" value="3" type="radio"> HP
</label>
</div>
Javascript
// Attach a generalised change handler to the radio buttons,
// braching out to a specific function as specified by
// the button's `data-changeHandler` property.
$(".btn-group input[type='radio']").on('change', function () {
changeHandlers[$(this).data('changeHandler')](this);
});
// Branching above is made simple by specifying
// the specific change handlers as properties of an object.
var changeHandlers = {
'switch_ledgers': function(button) {
$(button).filter(':checked').prop('checked', false).closest("label").removeClass('active');
changeHandlers.update_transaction(button);
},
'update_transaction': function(button) {
var transactionId = $(button).closest(".btn-group").data('transactionId'),
form = $("#transaction_" + transactionId);
$.ajax({
type: form.attr('method'),
data: form.serialize(),
url: form.attr('action')
}).done(function() {
update_balance();
update_total_balance();
});
}
}
现在,将其他按钮组中的HTML修改为与上面相同的模式。