0

this works to create a second pull down menu dynamically based on the result of the first pull down menu:

for (var i = 0; i < 1; i++) {
    $('#wdiv' + i).change(function() {
        var wdiv = $(this).val();

        $.ajax({
            type: "POST",
            url: "populate_classes.php",
            data: 'theOption=' + wdiv,
            success: function(whatigot) {
                $('#class_list' + i).html(whatigot);
            } 

        }); //END $.ajax
    }); //END dropdown change event 
}

why does the input from drop down select #wdiv0 change the drop down menu #class_list1? I want the #wdiv selection to set the #classlist0 drop down select.

Here is the portion of the form:

<fieldset><legend>Select Divisions</legend>              
  <table width="100%" border="0" cellspacing="0" cellpadding="5">
  <tr>
    <td><div align="center"><u><strong>Name</strong></u></div></td>
    <td><div align="center"><u><strong>Division</strong></u></div></td>
    <td><div align="center"><u><strong>Class</strong></u></div></td>
  </tr>
  <?php for ($i = 0; $i < $wrestlerkey; $i++) {    
      $sql = 'SELECT * FROM tourn_division AS td WHERE t_num = ?';
      $divresult = $dbConnect->fetchAll($sql, $_SESSION['tourn_id']);
      $divcount = count($divresult);
  ?>          
    <tr>
      <td width="20%" bgcolor="#CCCCCC"><div align="right"><?php echo $_SESSION['wfirst'][$i] . " " . $_SESSION['wlast'][$i] . ":"; ?></div></td>
      <td>
        <select name="<?php echo "wdiv" . $i ?>" id="<?php echo "wdiv" . $i ?>">
        <?php for ($d = 0; $d < $divcount; $d++) { ?>
          <option value="<?php echo $divresult[$d]->div_num; ?>"><?php echo $divresult[$d]->div_name; ?></option>
        <?php } ?>  
      </select></td>
      <td>
      <div id="<?php echo "class_list" . $i ?>"></div>
      </td>
    </tr>
    <?php } ?>
  </table>
</fieldset>  

2 Answers 2

1

It's happening because the AJAX callback handlers you create both share a reference to the same variable "i". To avoid that, you can create your "success" handler with a separate function edit — in fact, due to the nature of your code structure here, you need to make the whole "change" callback in a separate function:

function makeChangeHandler(listIndex) {
  return function() {
    var wdiv = $(this).val();

    $.ajax({
        type: "POST",
        url: "populate_classes.php",
        data: 'theOption=' + wdiv,
        success: function(whatigot) {
            $('#class_list' + listIndex).html(whatigot);
        } 
     });
  };
}

// ...

for (var i = 0; i < 2; i++) { // for 2, substitute actual number of elements involved
    $('#wdiv' + i).change( makeChangeHandler(i) );
}

That function will return the actual handler function. Each such function returned by "makeSuccessHandler" will have it's very own private copy of the loop index.

(Note edits made - the whole "change" handler needs to be constructed in the helper function.)

Sign up to request clarification or add additional context in comments.

7 Comments

as long as you make that success handler before being inside the change function, this should work
@JaimeMorales ooo good point!! I was working on adding back more of the original code anyway. Thanks!
do i put makeSuccesshandler prior to or inside the for loop?
@MattKeel somewhere outside the loop would be best.
OK, with above code setting #wdiv0 properly sets the new drop-down #class_list0 successfully. However, setting #wdiv1 has no effect on #class_list1
|
1

The ajax response is returning after the loop has finished, so it will always be the last value of i. You need to set a variable to i or put a closure around it:

    for (var i = 0; i < 1; i++) {
       var currentIndex = i; // this will not work (see comments below)
        $('#wdiv' + i).change({currentIndex: i}, function(e) {
            var wdiv = $(this).val();
            var currentIndex = e.data.currentIndex;
            $.ajax({
                type: "POST",
                url: "populate_classes.php",
                data: 'theOption=' + wdiv,
                success: function(whatigot) {
                    $('#class_list' + currentIndex).html(whatigot);
                } 

            }); //END $.ajax
        }); //END dropdown change event 
    }

or

for (var i = 0; i < 1; i++) {
   (function (i){
        $('#wdiv' + i).change(function() {
            var wdiv = $(this).val();

              $.ajax({
                type: "POST",
                url: "populate_classes.php",
                data: 'theOption=' + wdiv,
                success: function(whatigot) {
                    $('#class_list' + i).html(whatigot);
                } 

              }); //END $.ajax

        }); //END dropdown change event 
      })(i);
    }

5 Comments

That won't work, for the very same reason that using plain "i" won't work. The "currentIndex" variable isn't initialized until the "change" handler is actually called :)
currentIndex needs to be set outside of the function.
Still won't work, though your anonymous function version is fine. JavaScript variables are strictly scoped at the function level.
Because that local variable "currentIndex" is scoped exactly the same way that "i" is scoped. Thus, each of those event handlers has a reference to the exact same variable in the closure, so its value will be the same as "i" when the loop is finished.
yep. you are right. for this instance, I might want to use the event data to pass the correct index to the change function

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.