2

Apologies if this is daft but I'm going a bit mad with this issue i think. I keep getting an undefined error when logging my querySelectorAll to the console. I would like to add a click event on the querySelectorAll selector below eventually once i can work out the issue. All i want is the btn click handler to work when the section has class active.

<section class="section test active">
  <div class="btn"></div>
</section>

<section class="section test">
  <div class="btn"></div>
</section>

var btn = document.querySelectorAll('.section.active .btn');
console.log(btn[0]);

This shows undefined.

What i am looking to do is something like

var btn = document.querySelectorAll('.section.active .btn');
    btn.addEventListener('click', function() {
 //Do something
});

EDIT Sorry i forgot to add the class section to the section tag

Appreciate any advice

Liam
  • 111
  • 2
  • 6
  • 13
  • 1
    `.` is a *class selector*, therefore `.section` is looking for the *class* of `section`, rather than a `
    ` element. To select an element by type, you simply avoid prefixing it. For example, `section` would select `
    `, and so on. Long story short: Drop the `.` before `section` :)
    – Tyler Roper May 29 '18 at 19:04
  • Thank Tyler, the reason i had the .section was because it was meant to have the class section I forgot to add it :-) – Liam May 29 '18 at 19:08
  • Cool. That said, you can't do `.addEventListener` on a *collection* of elements, but rather *one* element. You can loop through the collection to apply it to each, or apply it only to the first button for example by doing `btn[0].addEventListener` instead. – Tyler Roper May 29 '18 at 19:08
  • If you get no result from querySelectorAll then there was nothing to select when it was run. When/where was you code executed? – Musa May 29 '18 at 19:10

4 Answers4

0

.section is targeting elements with the class section. You meant to select <section> which has class .active. To make it work for a NodeList, you need to loop over the returned list, or use querySelector

var btns = document.querySelectorAll("section.active .btn");

[].forEach.call(btns, function(btn) {

  btn.addEventListener("click", function() {
    //Do something
  });

});
Adam Azad
  • 11,171
  • 5
  • 29
  • 70
  • Thanks very much for this, I actually forgot to add the class section to my section element which i have just amended which is why i was using .section.active – Liam May 29 '18 at 19:10
  • 1
    @TylerRoper, thanks for the heads up. :) – Adam Azad May 29 '18 at 19:11
0

You're trying to assign the event to a HTMLCollection vs. one particular element. Won't work. Instead, loop through the collection and individually assign the event to each element as so:

var btn = document.querySelectorAll('.section.active .btn');

Array.prototype.forEach.call(btn, function(elem) {
  elem.addEventListener('click', function() {
    console.log('clicked');
  });
});
<section class="section test active">
  <div class="btn">Active Button</div>
</section>

<section class="section test">
  <div class="btn">Button</div>
</section>
Carl Edwards
  • 13,826
  • 11
  • 57
  • 119
  • thanks Carl for this, I've not used prototype.for.each.call before. Will have to look into this, im fairly new to javascript – Liam May 29 '18 at 19:19
  • No worries. Being that what you're trying to loop through is an HTMLCollection as I stated before, doing a simple `forEach` won't work (because it's technically not an array). That's why using `call` from the array prototype is necessary here. It's the most browser safe solution. Otherwise, `Array.from(btn)` could also be used in this case. – Carl Edwards May 29 '18 at 19:21
0

Try the following code. You are putting a . before section which is wrong

var btn = document.querySelectorAll('.section.active .btn');
console.log(btn[0]);

var btn = document.querySelectorAll('.section.active .btn');
btn.forEach((b)=> {
   b.addEventListener('click', function() {
      // Do something
  });
})
<section class="section test active">
  <div class="btn"></div>
</section>

<section class="test">
  <div class="btn"></div>
</section>
Md Johirul Islam
  • 5,042
  • 4
  • 23
  • 56
  • Thanks very much @md Johirul Islam for this, I actually forgot to add the class section to my section element which i have just amended which is why i was using .section.active – Liam May 29 '18 at 19:11
0

Your selector is wrong(the dot before section), it should be

var btn = document.querySelectorAll('section.active .btn');

Also querySelectorAll returns a list of elements, you will have to add the event handler to each element individually.

for (var x = 0; x < btn.length; x++){
    btn[x].addEventListener('click', function() {
     //Do something
    });
}
Musa
  • 96,336
  • 17
  • 118
  • 137
  • Thanks @Musa i will try the loop you suggest, I actually forgot to add the class section to my section element which i have just amended which is why i was using .section.active – Liam May 29 '18 at 19:12