在jQuery完成修改表单中的值之前提交表单

时间:2015-05-25 22:54:46

标签: javascript jquery forms jquery-deferred

这就是我要做的事情:当点击单选按钮时,我想更新表单中的某些值,只有在更新这些值后,才提交整个表单。我遇到的问题是,在更新值之前提交表单。

这是我目前的(非工作)实施:

<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();
    });
}

我希望我足够清楚我要做的事情。

谢谢!

3 个答案:

答案 0 :(得分:1)

您似乎直接在第一个输入元素的onchange事件中调用update_transaction()。

你不应该在改变事件中调用switch_ledgers()吗?

例如:

<input onchange="switch_ledgers(78)" id="radio_2_78" name="ledger_id" value="2" type="radio">

答案 1 :(得分:0)

在我看来,问题在于当您实际尝试将其作为update_transaction()的回调函数传递时执行.done()

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()

答案 2 :(得分:0)

直截了当地,您只需要修复switch_ledgers(),以免立即致电update_transaction()(Peter Herdenborg的回答)。

更进一步,你可以(而且应该):

  • deactivate_radio()清除延迟/承诺,这是完全同步的。
  • 在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以遵循与上面相同的模式。