简体   繁体   中英

Cannot get selected value of select with jQuery when the select has been set with jQuery

I am trying to create some cascading dropdowns, I have this I built function which half works:

 function CascadeDropDowns(parentClass, childClass, action) {

   var DropDownId = $(parentClass + " option:selected").val();

   $.ajax({
     url: "/Terminals_configuration/" + action,
     data: { DropDownId: DropDownId },
     dataType: "json",
     type: "POST",
     error: function () {
       alert("An error occurred.");
     },
     success: function (data) {
       var items = "";
       $.each(data, function (i, item) {
           items += "<option value=\"" + item.Value + "\">" + item.Text + "</option>";
       });
         $(childClass).html(items);
         $(childClass)[0].selectedIndex = 0;
     }
   });
  }

    $(document).ready(function(){
      $(".DeviceTypeDDL").change(function () {
        CascadeDropDowns(".DeviceTypeDDL", ".ConfigGroupDDL", "GetGroups");
        CascadeDropDowns(".ConfigGroupDDL", ".ConfigNameDDL", "GetParameters");
      });
      $(".ConfigGroupDDL").change(function () {
        CascadeDropDowns(".ConfigGroupDDL", ".ConfigNameDDL", "GetParameters");
      });
    });

Relevant HTML - Link to jQuery v1.8.2 not included here!

<form action="/Terminals_configuration" method="post">    <fieldset>
      <legend>
        <h2>Configuration settings</h2>
      </legend>

      <div class="editor-label">
        <label for="DeviceType">Device type</label>
      </div>
      <div class="editor-field">
        <select class="DeviceTypeDDL" data-val="true" data-val-number="The field DeviceTypeSelectedItem must be a number." id="DeviceTypeSelectedItem" name="DeviceTypeSelectedItem"><option value="8">IT</option>
<option value="9">RS</option>
</select>
        <span class="field-validation-valid" data-valmsg-for="DeviceTypeSelectedItem" data-valmsg-replace="true"></span>
      </div>

       <div class="editor-label">
        <label for="ConfigGroup">ConfigGroup</label>
      </div>
      <div class="editor-field">
        <select class="ConfigGroupDDL" data-val="true" data-val-number="The field ConfigGroupSelectedItem must be a number." id="ConfigGroupSelectedItem" name="ConfigGroupSelectedItem"><option value="-1">No value</option>
</select>
        <span class="field-validation-valid" data-valmsg-for="ConfigGroupSelectedItem" data-valmsg-replace="true"></span>
      </div>

       <div class="editor-label">
        <label for="ConfigName">ConfigName</label>
      </div>
      <div class="editor-field">
        <select class="ConfigNameDDL" data-val="true" data-val-number="The field ConfigNameSelectedItem must be a number." id="ConfigNameSelectedItem" name="ConfigNameSelectedItem"><option value="-1">No value</option>
</select>
        <span class="field-validation-valid" data-valmsg-for="ConfigNameSelectedItem" data-valmsg-replace="true"></span>
      </div>

        <div class="editor-label">
        <label for="ConfigValue">ConfigValue</label>
      </div>
      <div class="editor-field">
        <input class="text-box single-line" data-val="true" data-val-required="Please enter the configuration value" id="ConfigValue" name="ConfigValue" type="text" value="" />
        <span class="field-validation-valid" data-valmsg-for="ConfigValue" data-valmsg-replace="true"></span>
      </div>

        <div class="editor-label">
        <label for="MergeOrDelete">MergeOrDelete</label>
      </div>
      <div class="editor-field">
        <select class="MergeDeleteDDL" data-val="true" data-val-number="The field MergeOrDeleteSelectedItem must be a number." id="MergeOrDeleteSelectedItem" name="MergeOrDeleteSelectedItem"><option value="0">Delete</option>
<option value="1">Merge</option>
</select>
        <span class="field-validation-valid" data-valmsg-for="MergeOrDeleteSelectedItem" data-valmsg-replace="true"></span>
      </div>


      <p>
        <input type="submit" value="Add" />
      </p>
    </fieldset>
</form>

The issue is When the first dropdown is changed i will need to populate the two children. And when the second dropdown is changed I only need to populate the one child.

I thought that by setting $(childClass)[0].selectedIndex = 0; then this would make this value selected, so that when the function fires a second time with the child dropdown that has just been populated it would be able to get this value, but it doesn't.

I'm thinking maybe the new are not available in the DOM at this point but im not sure.

Any help would be great.

It might be, that your second CascadeDropDowns function is executed before the first one has finished its execution (since you're doing an AJAX call, which is asynchronous).

One way of making the second function wait for the first one is by utilizing jQuery deferreds:

function CascadeDropDowns(parentClass, childClass, action) {

   var completeDeferred = $.Deferred();
   var DropDownId = $(parentClass + " option:selected").val();

   $.ajax({
     url: "/Terminals_configuration/" + action,
     data: { DropDownId: DropDownId },
     dataType: "json",
     type: "POST",
     error: function () {
       alert("An error occurred.");
     },
     success: function (data) {
       var items = "";
       $.each(data, function (i, item) {
           items += "<option value=\"" + item.Value + "\">" + item.Text + "</option>";
       });
         $(childClass).html(items);
         $(childClass)[0].selectedIndex = 0;
         completeDeferred.resolve();
     }
   });

   return completeDeferred;
}

then use the returned deferred:

$(".DeviceTypeDDL").change(function () {
    var deferred = CascadeDropDowns(".DeviceTypeDDL", ".ConfigGroupDDL", "GetGroups");
    deferred.then(function() {
        CascadeDropDowns(".ConfigGroupDDL", ".ConfigNameDDL", "GetParameters");
    })
});

An easier way might be to modify the function to accept a callback:

function CascadeDropDowns(parentClass, childClass, action, callback) {
   var DropDownId = $(parentClass + " option:selected").val();

   $.ajax({
     url: "/Terminals_configuration/" + action,
     data: { DropDownId: DropDownId },
     dataType: "json",
     type: "POST",
     error: function () {
       alert("An error occurred.");
     },
     success: function (data) {
       var items = "";
       $.each(data, function (i, item) {
           items += "<option value=\"" + item.Value + "\">" + item.Text + "</option>";
       });
         $(childClass).html(items);
         $(childClass)[0].selectedIndex = 0;
         if (callback) {
             callback();
         }
     }
   });
}

then use it like this:

$(".DeviceTypeDDL").change(function () {
    var callback = function() {
        CascadeDropDowns(".ConfigGroupDDL", ".ConfigNameDDL", "GetParameters");
    };
    CascadeDropDowns(".DeviceTypeDDL", ".ConfigGroupDDL", "GetGroups", callback);
});

If you know the value of the option you need to select, you can just use:

$(childClass).val(valOfOption);

There are some other options posted here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM