jQuery - 回调函数下拉列表加载

4

在下拉列表加载后,我需要从中选择一个值:

编辑:与视图相关联的脚本中,我有以下内容:

//Dropdown cascade call when trigger is called and fill councilDropdown:
$("#districtDropdown").cascade({
    url: "/Address/ListCouncilByDistrict",
    paramName: "districtId",
    firstOption: 'Selecione o Concelho...',
    childSelect: $("#councilDropdown")
});

$("#PostalCode").keyup(function () {
loadPTPostalCode();
});

$("#PostalCodeExtension").keyup(function () {
    loadPTPostalCode();
});


function loadPTPostalCode()
{
  if ($("#PostalCode").val() >= 1000) {
    $.ajax({
        url: '/Address/GetPTPostalCode',
        type: "POST",
        dataType: "json",
        data: { postalCode: $("#PostalCode").val(), postalCodeExtension: $("#PostalCodeExtension").val() },
        success: function (data) {
            if (data != null) {
                $("#districtDropdown").val(data.PTDistrict_Id); // Set the Dropdown value
                $('#districtDropdown').trigger('change'); // Trigger (force the dropdown to load

                // *** This is done to soon, the dropdownlist of the Councils is not all loaded yet ***
                $("#councilDropdown").val(data.PTCouncil_Id);
            }
        },
        error: function (XMLHttpRequest, textStatus, errorThrown) {
            alert(textStatus)
        }
    });
}

}

编辑: 视图

@model Heelp.ViewModels.AddressPTViewModel

<h2>Create</h2>

@using (Ajax.BeginForm(MVC.Address.CreateAddressPT(), new AjaxOptions { OnSuccess = "showLoginConfirmationResultMessage" }, new { @id = "AddressForm" }))
{
@Html.AntiForgeryToken()

<div class="address1">
    @Html.LabelFor(model => model.Address1)
    @Html.TextBoxFor(model => model.Address1)
    @Html.ValidationMessageFor(model => model.Address1)
</div>
<div class="address2">
    @Html.TextBoxFor(model => model.Address2)
    @Html.ValidationMessageFor(model => model.Address2)
</div>
<div class="city">
    @Html.LabelFor(model => model.City)
    @Html.TextBoxFor(model => model.City)
    @Html.ValidationMessageFor(model => model.City)
</div>
<div class="postalCode">
    @Html.DisplayNameFor(m => m.PostalCode)
    @Html.TextBoxFor(m => m.PostalCode, new { @Value = "" })
    @Html.ValidationMessageFor(m => m.PostalCode)
</div>
<div class="postalCodeExtension">
    @Html.LabelFor(model => model.PostalCodeExtension)
    @Html.TextBoxFor(model => model.PostalCodeExtension)
    @Html.ValidationMessageFor(m => m.PostalCodeExtension)
</div>
<div class="postalCodeCity">
    @Html.LabelFor(model => model.PostalCodeCity)
    @Html.TextBoxFor(model => model.PostalCodeCity)
    @Html.ValidationMessageFor(m => m.PostalCodeCity)
</div>
<div id="district">
    @Html.DisplayNameFor(m => m.PTDistrict_Id)
    @Html.DropDownListFor(m => m.PTDistrict_Id, Model.PTDistrictList, HeelpResources.PTDistrictViewDropDownListFirstRecord, new { id = "districtDropdown" })
    @Html.ValidationMessageFor(m => m.PTDistrict_Id)
</div>
<div id="council">
    @Html.DisplayNameFor(m => m.PTCouncil_Id)
    @Html.DropDownListFor(m => m.PTCouncil_Id, Model.PTCouncilList, HeelpResources.PTCouncilViewDropDownListFirstRecord, new { id = "councilDropdown" })
    @Html.ValidationMessageFor(m => m.PTCouncil_Id)
</div>
<p>
    <input type="submit" value="Create" />
</p>
}
<div>
 @Html.ActionLink("Back to List", "Index")
</div>

编辑:

级联功能:

// Cascade function
(function ($) {
$.fn.cascade = function (options) {
    var defaults = {};
    var opts = $.extend(defaults, options);

    return this.each(function () {
        $(this).change(function () {
            var selectedValue = $(this).val();
            if (selectedValue == '') {
                opts.childSelect.empty();
                return;
            }
            var params = {};
            params[opts.paramName] = selectedValue;
            $.post(opts.url, params, function (items) {
                //$.getJSON(opts.url, params, function (items) {
                opts.childSelect.empty();
                if (opts.firstOption != "")
                    opts.childSelect.append(
                        $('<option/>')
                            .attr('value', '')
                            .text(opts.firstOption));
                $.each(items, function (index, item) {
                    // alert(opts.firstOption);
                    opts.childSelect.append(
                        $('<option/>')
                            .attr('value', item.Id)
                            .text(item.Name)
                    );
                });
            });
        });
    });
};
})(jQuery);

但是当我这样做时,因为下拉框尚未加载,所以val()还不存在。

例如,如果我在之前放置一个警报消息,它可以正常工作,因为它有时间来加载下拉菜单。

如何在下拉菜单加载后仅设置委员会下拉菜单的值?


我有点困惑。从你的措辞中看起来,好像你想在用户选择值之前使用districtDropdown的值。我确定不是这样,请进一步澄清。 - Dave Alperovich
由于没有准备好的事件,很难看到您所做更改的顺序(强制顺序)。 - Dave Alperovich
@amhed 你好,我已经写好了你提出的问题的代码。谢谢。 - Patrick
2
您触发了一个更改函数。之后,您想要的 PTCouncil_Id 的值无法正常工作,因为更改还没有准备好?定义回调函数? - gulty
正如@gulty所说,当您触发事件时,将调用$("#districtDropdown").cascade(),这会发起一个ajax调用并尝试在加载之前访问该值。我不确定该插件的工作原理,但最好设置回调函数,以便在加载后传递该值。 - amhed
显示剩余5条评论
4个回答

4
根据您的要求 "只有在下拉列表加载完成后才设置委员会下拉列表的值",您需要执行同步Ajax请求。您可以将选项 async 设置为false 以获取同步Ajax请求。
$.ajax({
    url: '/Address/GetPTPostalCode',
    type: "POST",
    dataType: "json",
    data: { postalCode: $("#PostalCode").val(), postalCodeExtension: $("#PostalCodeExtension").val() },
    success: function (data) {
        if (data != null) {
            $("#districtDropdown").val(data.PTDistrict_Id); 
            $('#districtDropdown').trigger('change'); 

            // *** This is done to soon, the dropdownlist of the Councils is not all loaded yet ***
            $("#councilDropdown").val(data.PTCouncil_Id);
        }
    },
    async:   false
});

1
"async=false" 在 jQuery 1.8 中已被弃用。 - Pow-Ian

3
我会更新级联插件,以便在下拉列表更新时触发事件。
(function ($) {
$.fn.cascade = function (options) {
    var defaults = {};
    var opts = $.extend(defaults, options);

    return this.each(function () {
        $(this).change(function () {
            // #### store reference to changed element for later ####
            var self = this,
                selectedValue = $(this).val();
            if (selectedValue == '') {
                opts.childSelect.empty();
                return;
            }
            var params = {};
            params[opts.paramName] = selectedValue;
            $.post(opts.url, params, function (items) {
                //$.getJSON(opts.url, params, function (items) {
                opts.childSelect.empty();
                if (opts.firstOption != "")
                    opts.childSelect.append(
                        $('<option/>')
                            .attr('value', '')
                            .text(opts.firstOption));
                $.each(items, function (index, item) {
                    // alert(opts.firstOption);
                    opts.childSelect.append(
                        $('<option/>')
                            .attr('value', item.Id)
                            .text(item.Name)
                    );
                });
                // #### Trigger event ####
                self.trigger("update");
            });
        });
    });
};
})(jQuery);

现在你可以绑定到它:

    ...
    // *** #### fixed #### This is done to soon, the dropdownlist of the Councils is not all loaded yet ***
    $("#councilDropdown").on("updated",function(){
        $(this).val(data.PTCouncil_Id);
    });
}

1
尝试在下拉菜单1上创建两个事件。第一个是自定义事件,第二个是更改事件。
当用户手动更改下拉菜单的值时,将触发更改事件。
$('#dictrctDropdown').change(function (event){
    $('#dictrctDropdown').trigger('custom');
});

$('#dictrctDropdown').on('custom', function (event, param1){
    // Load council dropdown 
    if(param1){
       $("#councilDropdown").val(param1);
    }
});

成功调用"/Address/GetPTPostalCode",触发“dictrctDropdown”自定义事件。

function loadPTPostalCode()
{
  if ($("#PostalCode").val() >= 1000) {
    $.ajax({
        url: '/Address/GetPTPostalCode',
        type: "POST",
        dataType: "json",
        data: { postalCode: $("#PostalCode").val(), postalCodeExtension: $("#PostalCodeExtension").val() },
        success: function (data) {
            if (data != null) {

        $.getJSON('disctrictURL','data to post (if any)',function(response){
        //Load district dropdown
    /*
    $.each(items, function (index, item) {
                        // alert(opts.firstOption);
                        opts.childSelect.append(
                            $('<option/>')
                                .attr('value', item.Id)
                                .text(item.Name)
                        );
                    });

    */
        $("#districtDropdown").val(data.PTDistrict_Id); // Set the Dropdown value
        });

        //Now use district id load council dropdown and set value 
    $.getJSON('councilURL','data to post (if any)',function(response){
    //Council dropdown
    $("#districtDropdown").val('council id'); // Set the Dropdown value
    });

               }
            },
            error: function (XMLHttpRequest, textStatus, errorThrown) {
                alert(textStatus)
            }
        });
    }

希望这可以帮到你!

嗨,谢谢但还是不行。别忘了下拉框必须在 Json 调用后加载,而且先加载区再加载议会。Json 给我这两个值,我只需要等待下拉框加载完毕即可设置这些值。 - Patrick
为此,您应该在'/Address/GetPTPostalCode'的成功回调中进行另一个AJAX请求来加载地区下拉菜单,并在加载地区下拉菜单时设置其值。 - vijay
同样的方法也可以用在另一个下拉菜单上,这肯定会解决你的问题。 - vijay
但是在加载完成后,我该如何设置CouncilDropdown的值呢? - Patrick
请检查更新的帖子,我已经添加了代码片段来加载区域下拉菜单和议会下拉菜单,一旦加载完成,您就可以发送其值。 - vijay

1
我认为这里有两种方法。

1

最佳实践是为您的级联添加回调功能。可以像这样完成:
...
$.post(opts.url, params, function (items) {
 //$.getJSON(opts.url, params, function (items) {
 opts.childSelect.empty();
 if (opts.firstOption != ""){
  opts.childSelect.append(
   $('<option/>')
   .attr('value', '')
   .text(opts.firstOption));
  $.each(items, function (index, item) {
   // alert(opts.firstOption);
   opts.childSelect.append(
    $('<option/>')
     .attr('value', item.Id)
     .text(item.Name)
    );
  });
  if( typeof(opts.callback) == "function" )opts.callback();//issue callback
 }
});
...

它将在此处设置级联使用:

$("#districtDropdown").cascade({
 url: "/Address/ListCouncilByDistrict",
 paramName: "districtId",
 firstOption: 'Selecione o Concelho...',
 childSelect: $("#councilDropdown"),
 callback: function(){ districtCallback(); }
});

并且可以按照您想要的方式进行定义,就像这样:

function districtCallback(){
 $("#councilDropdown").val($("#districtDropdown").val());
}

2

快速而简单的... jsFiddle演示
success: function (data) {
 if (data != null) {
  $("#districtDropdown").val(data.PTDistrict_Id); // Set the Dropdown value
  $('#districtDropdown').trigger('change'); // Trigger (force the dropdown to load
  (function councilVal(){
   if( typeof($("#councilDropdown").val()) != "undefined" ){
    $("#councilDropdown").val(data.PTCouncil_Id);
   }else{
    setTimeout(councilVal,50);
   }
  })()
 }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接