jquery 等待第一个下拉列表的更改事件,然后选择第二个下拉值

时间:2021-04-05 15:13:19

标签: javascript html jquery asp.net-core

我的网页上有两个选择控件(Bootstrap Select2):

<div class="form-group">
    <label>Client: </label>
    <select id="ddlClient" class="form-control select2 subselect">
        <option value="0">Select client</option>
    </select>
</div>

<div class="form-group">
    <label>Policy: </label>
    <select id="ddlPolicy" class="form-control select2">
        <option value="0">...</option>
    </select>
</div>

我在第一个 ddlClient 上有一个监听器,用于根据客户端选择填充第二个的值:

$(document).ready(function () {
    $('.content').on('change', 'select.subselect', function () {

    var subItems = "<option value='0'>... select policy ... </option>";

    var idSelect = $('#ddlClient').val();

    // fill list
    $.getJSON("@Url.Action("GetPolicies", "Home")", {id: idSelect }, function (data) {

        $.each(data, function (index, item) {
            subItems += "<option value='" + item.value + "'>" + item.text + "</option>";
        });

        $("#ddlPolicy").html(subItems);
        $("#ddlPolicy").val('0');
    });     
});

现在,在某些情况下,我必须以编程方式更改两个下拉列表,问题是下面的函数(第 3 行和第 4 行)显然不会等待 change 事件完成。因此,策略没有正确选择:

$('#ddlClient').val(someClientValue);
$('#ddlClient').trigger('change'); //trigger change so that SELECT2 changes text
$('#ddlPolicy').val(somePolicyValue);
$('#ddlPolicy').trigger('change'); //trigger change so that SELECT2 changes text

如何在调用 change 之前等待 ddlClient$('#ddlPolicy').val(somePolicyValue); 上完成?

我尝试过但不起作用的内容 (How to get jQuery to wait until an effect is finished?):

$('#ddlClient').val(someClientValue);
$('#ddlClient').change().promise().done(function () {
   $('#ddlPolicy').val(somePolicyValue);
   $('#ddlPolicy').trigger('change'); 
}

我也尝试过实现 .when

$('#ddlClient').val(someClientValue);
$.when($('#ddlClient').trigger('change')).then(function () {
    $('#ddlPolicy').val(somePolicyValue);
    $('#ddlPolicy').trigger('change');
}

但问题依然存在。

3 个答案:

答案 0 :(得分:0)

没有“内置”方式来通知 jQuery 您的更改事件执行了一些必须等待的异步工作。因此,您最好的选择是将用于填充第二个下拉列表的逻辑移动到其自己的函数中,该函数返回一个 Promise。从 change 事件中,您无需等待此承诺完成,而是从您的代码中需要等待它完成,然后再执行您await 的下一个操作。

首先几乎完全扩展你所拥有的,除了使用承诺而不是使用回调:

function loadSubitems() {
    
    var idSelect = $('#ddlClient').val();

    // fill list
    return $.getJSON("@Url.Action("GetPolicies", "Home")", {id: idSelect })
            .then(data => {
                   var subItems = "<option value='0'>... select policy ... </option>";

                   $.each(data, function (index, item) {
                      subItems += "<option value='" + item.value + "'>" + item.text + "</option>";
                   });

                    $("#ddlPolicy").html(subItems)
                                   .val('0');
            });     
}

此代码返回一个承诺,但您不需要像事件处理程序那样在已经异步的上下文中等待它完成:

$(document).ready(function () {
    $('.content').on('change', 'select.subselect', loadSubitems);
});

但是在您需要设置它的代码中,请确保它本身是一个 async 函数,并根据需要 await

(async function(){
   $('#ddlClient').val(someClientValue);
   await loadSubitems();
   $('#ddlPolicy').val(somePolicyValue);
})();

答案 1 :(得分:0)

.trigger() 根据 documentation 可以将额外的参数传递给事件,所以我会这样做。 例如,您可以更改 change 事件以在完成后执行回调。
例如

$('#ddlClient').on('change', (event, callback = undefined) => {
    // something
    if (callback != undefined) {
        callback();
    }
});

然后不是按顺序调用它们,而是将第二个触发器作为回调传递给第一个触发器

$('#ddlClient').val(12);
$('#ddlClient').trigger('change', triggerDdlPolicy);

const triggerDdlPolicy = () => {
    $('#ddlPolicy').val(12);
    $('#ddlPolicy').trigger('change');
}

完整片段
$(() => {
    triggerDdlClient();
});

$('#ddlClient').on('change', (event, callback = undefined) => {
    // something
    if (callback != undefined) {
        callback();
    }
});

const triggerDdlClient = () => {
    $('#ddlClient').val(12);
    $('#ddlClient').trigger('change', triggerDdlPolicy);
}

const triggerDdlPolicy = () => {
    $('#ddlPolicy').val(12);
    $('#ddlPolicy').trigger('change');
}

答案 2 :(得分:0)

我管理通过将输入参数改变事件(即param=undefined),然后政策下拉不同基于谁被触发改变事件乳宁来解决这个问题。

相关问题