Adam
Adam

Reputation: 1699

Event listener giving error

I have this code for example:

<html>
<input class="basketQuantity" type=number>Basket item 1</input>
<input class="basketQuantity" type=number>Basket item 2</input>
</html>

<script>
quantityInputs = document.querySelectorAll(".basketQuantity");
for(var i in quantityInputs){
    quantityInputs[i].addEventListener('change', function(){
        console.log(quantityInputs[i]);
    });
}
</script>

When i run it i get the error message:

TypeError: quantityInputs[i].addEventListener is not a function

Could anyone tell me why this is happening?

Upvotes: 0

Views: 322

Answers (3)

Alex
Alex

Reputation: 11255

quantityInputs = document.querySelectorAll(".basketQuantity");

First of all quantityInputs is the NodeList object. So

for(var i in quantityInputs){
    console.log(i);
}

will return all enumerable properties - from quantityInputs object and it prototype chain, not only its own (just quantityInputs enumerable properties). for .. in will return also length field and item enumerable properties from prototype chain and this properties are not DOM nodes and so don't have addEventListener method.

You must use Object.keys:

var nodeArray = [].slice.call(document.querySelectorAll(".basketQuantity"));

Object.keys(nodeArray).forEach(function (node) {
    // node.addEventListener
});

OR

or for .. in with hasOwnProperty check:

quantityInputs = document.querySelectorAll(".basketQuantity");
for(var i in quantityInputs){
    if (quantityInputs.hasOwnProperty(i)) {
        // quantityInputs[i].addEventListener
    }
}

OR

In the future (ES6) you can use in this case for .. of loop:

var quantityInputs = document.querySelectorAll("basketQuantity");

for (var node of quantityInputs) {
    console.log(node.addEventListener);
}

Note(thanks to @Teemu):

Also you have a error in your handler with i:

quantityInputs[i].addEventListener('change', function(){
    console.log(quantityInputs[i]);// return value of quantityInputs last i
});

so better use this for addEventListener target:

quantityInputs[i].addEventListener('change', function(){
    console.log(this);
});

Upvotes: 1

Ofer Haber
Ofer Haber

Reputation: 628

You are iterating on a nodeList:

 quantityInputs = document.querySelectorAll(".basketQuantity");
    [].forEach.call(quantityInputs, function (e) {
        e.addEventListener('click', function () {
            console.log("hello")
        }, false)
    })

Upvotes: 0

Victor
Victor

Reputation: 5131

The JavaScript for/in statement loops through the properties of an object, so your var i sometimes receives properties of the array quantityInputs, like length.

Just change your loop to a convencional, like for (i = 0; i < quantityInputs.length; i++) {... and it should works:

quantityInputs = document.querySelectorAll(".basketQuantity");
for (i = 0; i < quantityInputs.length; i++) {
    quantityInputs[i].addEventListener('change', function(){
        console.log('foo');
    });
}

Take a look here for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in

Upvotes: 0

Related Questions