Reputation: 116810
I have three radio buttons like this:
<input type="radio" name="P_1" value="1">Yes</input>
<input type="radio" name="P_1" value="2">No</input>
<input type="radio" name="P_2" value="1">Yes</input>
<input type="radio" name="P_2" value="2">No</input>
<input type="radio" name="P_3" value="1">Yes</input>
<input type="radio" name="P_3" value="2">No</input>
I am trying to add a listener to each of these radio buttons so that I will be notified when they change. I am doing something like this:
for (var i = 1; i <= 3; i++) {
$("input[name='P_" + i + "']").live('change', function () {
doProcessing("P_" + i, $("input[name='P_" + i + "']:checked").val());
});
}
However, this does not seem to work. It calls doProcessing
with i
set to 4 because that is the value of i
at the end of the for loop. What is the correct way of adding an event handler in my case?
Upvotes: 2
Views: 7778
Reputation: 179046
As with any asynchronous iterative value, you need to close over the value in the loop:
for (i = 0; i < 3; i++) {
(function(i){
...your code here...
}(i));
}
By the time the event handler is called, the value of the i
variable will have reached its maximum value (in this case 3
).
An alternative means of passing data to each handler, would be to use the data
parameter of the on
method:
for (i = 0; i < 3; i++) {
$(...selector...).on('change', null, {i:i}, function (e) {
//access the i value with: e.data.i
});
}
It would probably be better to simply check for the right value within the handler, and use a class to attach the event:
$(document).on('change', '.someClass', function (e) {
var i,
$this;
$this = $(this);
i = $(this).attr('name').substr(2);
i = parseInt(i, 10);
...your code here...
});
If you can't change the markup, then you can use '[name^="P_"]'
in place of '.someClass'
.
Upvotes: 2
Reputation: 6416
Try
$('input:radio').on('change', function(){
//access value of changed radio group with $(this).val()
});
Or, if you're using < jQuery 1.7
$('input:radio').live('change', function(){
//do stuff with $(this).val()
});
Upvotes: 8
Reputation: 71908
You have to use a closure that will remember the index value on each step. Here is one of the many possible ways to do that:
for (var i = 1; i <= 3; i++) {
$("input[name='P_" + i + "']").live('change', createListener(i));
}
function createListener(index) {
return function() {
doProcessing("P_" + index, $("input[name='P_" + index + "']:checked").val());
}
}
Upvotes: 1