I am assigning event listeners inside of a loop. I am passing a variable that changes throughout the loop into the event listener function. However I am having a problem. All of the event listeners are receiving the last value of the variable in the loop, instead of the value that I meant to send at each point in the loop. The function where I assign the event listeners is the following
let arr;
let newElem;
let id;
for (let i = 6; i < 13; i++) {
arr = this.state.cards[i];
if (arr.length > 1) {
for (let j = 0; j < arr.length; j++) {
if (j !== arr.length-1) {
newElem = document.createElement('div');
newElem.id = 'p' + i + '-' + (j+1);
document.getElementById('p' + i + '-' +
j).appendChild(newElem);
} else {
id = 'p' + i + '-' + j;
document.getElementById(id).className = 'cardLocations
faceUp';
newElem = document.createElement('p');
newElem.innerHTML = arr[j].id;
document.getElementById(id).appendChild(newElem);
document.getElementById(id).addEventListener('click', () =>
{this.selectCardsFromBoard(id)});
}
}
} else {
newElem = document.createElement('p');
newElem.innerHTML = arr[0].id;
document.getElementById('p6-0').appendChild(newElem);
document.getElementById('p6-0').addEventListener('click', () =>
{this.selectCardsFromBoard('p6-0')});
}
The problem is that whenever I click on any of the divs that I assigned event listeners to, the function selectCardsFromBoard is called with the same value and that is the final value that 'id' reaches in the loop. I want to be able to call the function with the value that 'id' is when it is assigned. I think this is some kind of pass by reference issue but I can't figure it out.
You want your id variable to be declared within the context of your for loop. Currently you are declaring id as a global variable and by the time your event is called the loop has already ran all the way through. All you need to do to fix it is get rid of the let id;' at the top of the program and change
let id;' at the top of the program and change
id = 'p' + i + '-' + j; to
let id = 'p' + i + '-' + j;`
That's because all event handler share the same id
variable. You can either defined it inside the loop so that it is scoped per iteration, or change the event handler to
document.getElementById(id).addEventListener(
'click',
event => this.selectCardsFromBoard(event.currentTarget.id)
);
For more general information about the problem see JavaScript closure inside loops – simple practical example
I would probably completely remove the id
variable and do
// outside the loops
const clickHandler = event => this.selectCardsFromBoard(event.currentTarget.id)
// ...
const element = document.getElementById('p' + i + '-' + j);
element.className = 'cardLocations faceUp';
element.addEventListener('click', clickHandler);
// why is this variable defined outside of your loop?
const newElem = document.createElement('p');
newElem.innerHTML = arr[j].id;
element.appendChild(newElem);
Calling getElementById
repeatedly with the same argument is unnecessary. There are probably other things that could be improved (eg you could make use of event delegation instead of assigning the same handler to so many objects), this is only focusing on the id
variable.
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.