Simplicius
Simplicius

Reputation: 2105

document.getElementsByClassName(...) returns "... is not a function"

I just started learning Javascript today and decided to start with practical examples, for example a toggle function.


This is what I've been ended with so far:

document.getElementsByClassName("toggle").addEventListener("click", function() {
  if(this.classList.contains("toggled")) {
    this.classList.remove("toggled")
  }
  else {
    this.classList.add("toggled")
  }
})

However it returns the error: document.getElementsByClassName(...).addEventListener is not a function. I figure that I havn't declared the function correctly, but can't figure why. Here's a Codepen.

It's probably less of a problem as what I see it.

Upvotes: 1

Views: 3000

Answers (4)

Pranav Rustagi
Pranav Rustagi

Reputation: 2731

The problem with that is that, document.getElementsByClassName() returns array of DOM elements. To bind event to elements, you would have to iterate though each element, and bind event to it. Do it like this :

Convert the HTML collection before iterating :

[...document.getElementsByClassName("toggle")].forEach(function(item){
  item.addEventListener("click", function() {
    if(this.classList.contains("toggled")) {
      this.classList.remove("toggled")
    }
    else {
      this.classList.add("toggled")
    }
  })
});

OR


Using querySelectorAll() :

document.querySelectorAll(".toggle").forEach(function(item){
  item.addEventListener("click", function() {
    if(this.classList.contains("toggled")) {
      this.classList.remove("toggled")
    }
    else {
      this.classList.add("toggled")
    }
  })
});

For detecting click on any element other than with class toggle :

document.querySelector('body').addEventListener('click', function(event){
  if(!event.target.classList.contains('toggle'){
    //code to do
  }
});

Upvotes: 1

sibabrat swain
sibabrat swain

Reputation: 1368

Please prefer querySelectorAll over getElementsByClassName. In both cases you will give you an array of dom elements. So either you loop and bind the listener or take the certain index and it will work

const toggleButtons = document.querySelectorAll(".toggle")
if(toggleButton.length > 0) {
    toggleButtons[0].addEventListener('click', function(event) {
       if (this.classList.contains('toggled')) {
            this.classList.remove('toggled');
        } else {
            this.classList.add('toggled');
        }
    })
}

Upvotes: 1

Saravan Somanchi
Saravan Somanchi

Reputation: 66

Simply add the index of element. In your case 0

document.getElementsByClassName("toggle")[0].addEventListener("click", function() {
  if(this.classList.contains("toggled")) {
    this.classList.remove("toggled")
  }
  else {
    this.classList.add("toggled")
  }
})

Upvotes: 1

michaelT
michaelT

Reputation: 1711

The method document.getElementsByClassName (elements) returns an array of elements with this class. So when you want to access elements of the array you has to to something like:

let firstElement = document.getElementsByClassName("toggle")[0]

If you want to access exactly one element, use document.getElementById or document.querySelector('.toggle')

Upvotes: 1

Related Questions