Cannot read property 'toggle' of undefined?

Anyone have a solution for this problem I’m having.

Below is the JS code. I am trying to toggle a class onto an element which has already been created but it wont work. I am trying to toggle on the class “.remove”

Getting: “Cannot read property ‘toggle’ of undefined”

Any thoughts?



const redTarget = document.getElementsByClassName('red');

stop.addEventListener('click', function(){
    bullet.style.animationPlayState = "paused";
    aimer.classList.toggle("remove");
    start.classList.toggle("remove");
    stop.classList.toggle("remove");
    bullet.classList.toggle("remove");
    **redTarget.classList.toggle("remove");**
});


Not seeing the error. Help appreciated.

Can you provide a minimum working example? Or a pen or a repo?

1 Like

Here you go

I am trying to get the toggle class of remove toggled on so the redtargets show up once the stop button is clicked.

Right, but getElementsByClassName does not return an element, it returns " a live HTMLCollection of found elements", as explained in the docs.

This is easy to confirm. When I do:

stop.addEventListener('click', function(){
    bullet.style.animationPlayState = "paused";
    aimer.classList.toggle("remove");
    start.classList.toggle("remove");
    stop.classList.toggle("remove");
    bullet.classList.toggle("remove");
    console.log(redTarget)
    redTarget.classList.toggle("remove");
});

it logs:

[img.redtarget.red.remove, img.redtarget2.red.remove, img.redtarget3.red.remove, img.redtarget4.red.remove, img.redtarget5.red.remove, img.redtarget6.red.remove, img.redtarget7.red.remove, img.redtarget8.red.remove, img.redtarget9.red.remove, img.redtarget10.red.remove]

So, it is a collection of elements. When it tries to evaluate redTarget.classList, it comes back undefined. Then when it tries to find a method called toggle on that, it throws an exception - undefined can’t have methods or properties - and tells you:

Uncaught TypeError: Cannot read property ‘toggle’ of undefined
at HTMLButtonElement.

So, it’s trying to tell you what the problem is.

Looking at the docs for HMTLCollection, I see that it has a method called item to access an element by index. So, something like this should work:

    for(let i = 0; i < redTarget.length; i += 1) {
        redTarget.item(i).classList.toggle("remove");
    }

That seems to work. There might be a more elegant way, but I’m too tired to look for it. Please don’t just take my answer - understand how I troubleshot it and found the answer. I don’t normally manipulate DOMs like this (I’m a React Native developer) but I know how to log things out and use documentation - that’s the real lesson here.

1 Like

Thanks Kevin.

You are so right being a programmer is a lot of breaking down problems and working through them. Knowing what to search and where to search it helps too.

I am going to move through this answer but I’m also going to see if there is another answer to this problem which im sure there is.

Thanks for taking the time.

2 Likes