4

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?

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. 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) 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()? 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. 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? Commented Feb 12, 2013 at 13:40

4 Answers 4

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
});
Sign up to request clarification or add additional context in comments.

1 Comment

async=false was depreciated in jQuery 1.8
3

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

Comments

1

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

Comments

1

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 !

5 Comments

Hi, thanks but it's still not working. Don't forget that the dropdowns must be loaded after the Json call and first the district and then the council. Json give me those two values, I just need to wait for the dropdowns to be loaded to set the values.
For that you should make one more AJAX request to load district dropdown from success callback of '/Address/GetPTPostalCode' and on load district dropdown and set value of it
Do the same for another dropdown as well, surely this will solve your problem.
But how do I set the value of CouncilDropdown after it's loaded?
Please check updated post i have added code snippet to load district dropdown and council dropdown, and once it is loaded you can sent its value.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.