admin管理员组

文章数量:1289623

I need to select a value from a Dropdownlist after it has been loaded:

EDIT: In the script associated with the View I have:

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

}

EDIT: The View

@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>

EDIT:

Cascade Function:

// 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);

But when I do that, as the Dropdownlist is not still loaded, the val() is not there yet.

For example, if I put an alert message before, it works fine because it as time to load the dropdown.

How can I set the value of the council dropdown only after the dropdown is loaded?

I need to select a value from a Dropdownlist after it has been loaded:

EDIT: In the script associated with the View I have:

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

}

EDIT: The View

@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>

EDIT:

Cascade Function:

// 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);

But when I do that, as the Dropdownlist is not still loaded, the val() is not there yet.

For example, if I put an alert message before, it works fine because it as time to load the dropdown.

How can I set the value of the council dropdown only after the dropdown is loaded?

Share Improve this question edited Feb 13, 2013 at 2:32 Patrick asked Feb 12, 2013 at 1:58 PatrickPatrick 2,78116 gold badges68 silver badges131 bronze badges 10
  • I'm a little confused. Seems from your wording like you want to use the value of districtDropdown before user has selected value from it. I'm sure that's not it, please clarify further. – Dave Alperovich Commented Feb 12, 2013 at 2:03
  • also, since the is no ready event, it's hard to see the sequence of your changes (enforced sequence) – Dave Alperovich Commented Feb 12, 2013 at 2:10
  • Patrick, can you provide more info on the structure of you view? where are you declaring the event wireups? are you using $(document).ready()? – amhed Commented Feb 12, 2013 at 4:16
  • @Dave Hi, basicaly I have an input filled by the user with a value that will search in the database for the District value and Council value to be set, firstly in the District dropdown that will load the Council values (actually done by the trigger that activate the change and also the cascade function to fill the Council Dropdown) and after that, set in the Council Dropdown the value from the Database after all the values has been loaded. Hope this can clarify the question. – Patrick Commented Feb 12, 2013 at 13:07
  • 2 You trigger a change function. After that you want the value of.PTCouncil_Id which isn't working because the change isn't ready? Define a callback? – gulty Commented Feb 12, 2013 at 13:40
 |  Show 5 more ments

4 Answers 4

Reset to default 4 +25

As your requirement "set the value of the council dropdown only after the dropdown is loaded".

You need perform synchronous Ajax request. You can specify the async option to be false to get a synchronous Ajax request.

$.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
});

I would update the cascade plugin to trigger an event when the ddl is updated.

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

now you can bind to that:

    ...
    // *** #### 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);
    });
}

I would say there are two approaches here.

1

The best practice would just be to add a callback functionality to your cascade. It could be done like this:

...
$.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
 }
});
...

It would be used by setting up cascade here:

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

and defined in whatever manner you wanted like this:

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

2

Quick and dirty.. jsFiddle demo

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

Try creating two events on dropdown 1. custom event and 2. change event

When user manually changes then dropdown value then change event will be fired.

$('#dictrctDropdown').change(function (event){
    $('#dictrctDropdown').trigger('custom');
});

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

from "/Address/GetPTPostalCode" success call back raise custom event for "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)
            }
        });
    }

Hope this will help !

本文标签: javascriptJQueryCallback Dropdownlist loadStack Overflow