1

I have list of input area in the form with id like "contact1_title", "contact2_title", "contact3_title" ....

And I also have a list of selection in this form with id like "contact1_name", "contact2_name", "contact2_name" ....

I want to write a loop to dynamic bind the onchange function for the selections.

Here is my code:

for(var j=1;j<6;j++){                        
                    $('#contact'+j+'_name').change(function() {
                        alert(j);
                        //json.engineer is a json object
                        $('#contact'+j+'_title').val( json.engineer[this.selectedIndex-1].title );
                    });
}

When I change the selection, it always alert 6.

and title input area cannot be changed by select.

Does it mean the variable in javascript always change?

How can I bind an action dynamically?

I can hack it by using "this.name.split("_")[0]" but the code seems ugly.

Thanks in advanced.

Wangsu
  • 86
  • 1
  • 5

3 Answers3

2

Wrap your change functionality by closure:

for(var j=1;j<6;j++){     
    (function(j){                   
         $('#contact'+j+'_name').change(function() {
             alert(j);
             //json.engineer is a json object
             $('#contact'+j+'_title').val( json.engineer[this.selectedIndex-1].title );
         });
     })(j);
}

The problem was, when you click, your loop is already ended, so j is equal to 6.

Engineer
  • 47,849
  • 12
  • 88
  • 91
  • The event handler is already a closure. A more correct explanation would be: "Use an immediately executed function expression to create a new scope" (or something like that). – Felix Kling Jun 20 '12 at 18:51
  • @FelixKling What about my new explanation? – Engineer Jun 20 '12 at 18:53
1

Another solution would be to pass the counter as event data:

for(var j=1;j<6;j++){                        
    $('#contact'+j+'_name').change({index: j}, function(event) {
        $('#contact' + event.data.index + '_title')
           .val(json.engineer[this.selectedIndex-1].title );
    });
}

Even better would be if you could avoid using a for loop, but that depends on your markup and whether you have control over the created elements since you probably have to adjust them to do so.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
0

There is a closure already, use it efficiently.

for(var j=1;j<6;j++){                        
     $('#contact'+j+'_name').change(function() {
     var k=j;
     alert(k);
     //json.engineer is a json object
     $('#contact'+k+'_title').val( json.engineer[this.selectedIndex-1].title );
     });
}
totten
  • 2,769
  • 3
  • 27
  • 41