I can’t addEventListener to my own element I get the error "TypeError: i.getAttribute is not a function at HTMLLIElement." I get
HTML CODE:
<ul>
<li class="item"></li>
<li class="item"></li>
<li class="item"></li>
<li class="item"></li>
<li class="item"></li>
</ul>
JS:
var items = document.getElementsByClassName('item');
for (i of items) {
i.addEventListener("click", function(i) {
i.classList.add("selected");
})
}
ERROR:
TypeError: i.getAttribute is not a function
at HTMLLIElement.
3
Answers
Because
getAttribute
is not a function on Events. Andi
is anEvent
:If your goal is to access this
i
:Which, incidentally, should probably not be an implicit global and should explicitly declare the variable in the current scope:
Then don’t shadow it with another variable of the same name. Either remove the
Event
reference entirely if you don’t intend to use it:Or, if you do intend to use it, give it a different name:
You need to define i first.
hope this solve your issue
Your reuse of the
i
variable within the event callback isn’t referencing the element as you think it is, therefore causing the error.This all stems from the way you are attempting to loop over the selected elements and how you are attempting to access them when you loop.
getElementsByClassName()
should rarely (if ever) be used and most certainly not if you are going to loop over the returned node list.And, if you use the correct modern approach to getting the references, you can then use the modern
.forEach()
method to iterate over the node list.Then, during each iteration, when you set up the event handler, you can refer to the current item with the argument specified within the callback function of the
forEach()
method.Finally, within the event handler, you can refer to the element that triggered the event in the first place with the
this
identifier.Here would be the modern way to do this:
And, if you are wanting only the most recently clicked item to have the active class, you need to loop over all the items upon the click of any of them and remove the class first. Then, you can apply it to only the one that was just clicked. That would look like this: