Adding CSS class in Vanilla JS to querySelectorAll results


#1

<select>
  <option value="condition_1">Condition 1</option>
  <option value="condition_2">Condition 2</option>  
</select>

<div class="classone">
    <div class="class1"></div> 
    <div class="class1"></div> 
    <div class="class1"></div> 
    <div class="class1"></div> 
    <div class="class1"></div> 
    <div class="class1"></div>   
</div>

Take the above HTML code as an example.

Now when the condition two is selected. I want that w/o the page refresh the new class should be printed like this →

<div class="classone newclass">
    <div class="class1"></div> 
    <div class="class1"></div> 
    <div class="class1"></div> 
    <div class="class1"></div> 
    <div class="class1"></div> 
    <div class="class1"></div>   
</div>

and based on what CSS is written for newclass the HTML should adapt accordingly.


#2

Look at this: JSFiddle


#3

You add a change event listener to the select, and when its value equals "condition_2", you add that class to the div:

var select = document.querySelector('select') // use more specific selector here
var classOne = document.querySelector('.classone')

select.addEventListener('change', function (event) {
  if (event.target.value === 'condition_2') {
    classOne.classList.add('newclass')
  }
})

CSS associated with that class will of course apply then.


#4

Hi there, You know I am quiet new to all this can you be more specific please. Thanks.


#5

I mean you should give that select a unique class or an ID so that you can unambiguously query it... just "select" is pretty generic and it's probably not the only one on your page.


#7

I think your example is not completely working.


#8

Check this JS fiddle Version 2


#9

It is working, but what if we want this situation →

<div class="classone newclass">
    <div class="class1 newclass"></div> 
    <div class="class1 newclass"></div> 
    <div class="class1 newclass"></div> 
    <div class="class1 newclass"></div> 
    <div class="class1 newclass"></div> 
    <div class="class1 newclass"></div>   
</div>

Instead of this →

<div class="classone newclass">
    <div class="class1"></div> 
    <div class="class1"></div> 
    <div class="class1"></div> 
    <div class="class1"></div> 
    <div class="class1"></div> 
    <div class="class1"></div>   
</div>

I think queryselectorAll should work, but I tried but that ddint worked.


#10

Yes, either .querySelectorAll(), or in this case maybe just the .children of the select... so what exactly did you try?


#11

That can be taken care of with css using the parent 'newclass'. There is no need for the newclass also on the children unless you have some other structures?

e.g.

.newclass .class1 {rules here...}


#12

Perfect Make sense. Thanks!


#13

I used this →

var select = document.querySelector('select') // use more specific selector here
var classOne = document.querySelectorAll('.classone')

#14

That gets you all elements that have the class classone... I suppose you want all elements with the class class1? I.e.

var elements = document.querySelectorAll('.class1')

... or all together like

var elements = document.querySelectorAll('.classone, .class1')

#15

This actually doesn't work, and I am not sure how to use for each loop here →

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
        <div class="classone">
            <div class="class1">Tester Code</div>
            <div class="class1">Tester Code</div>
            <div class="class1">Tester Code</div>
            <div class="class1">Tester Code</div>
            <div class="class1">Tester Code</div>
            <div class="class1">Tester Code</div>
        </div>
        <script type="text/javascript">
            var select = document.querySelector('select') // use more specific selector here
            var classOne = document.querySelectorAll('.class1')

            select.addEventListener('change', function (event) {
            if (event.target.value === 'condition_2') {
                classOne.classList.add('newclass')
                }
            })
        </script>
    </body>
</html>

#16

There's probably a more efficient way but you could loop through them like this:

 var select = document.querySelector('select') // use more specific selector here
 var classOne = document.querySelectorAll('.class1')

 select.addEventListener('change', function(event) {
     if (event.target.value === 'condition_2') {
         for (i = 0; i < classOne.length; ++i) {
             classOne[i].classList.add('newclass')
         }
     }
 })

#17

You iterate over the items in the node list, and add that class to each; you can do so with an old for loop, a for...of loop or using the .forEach() method. Unless you need to break out of a loop early, I would generally recommend using the latter:

var elements = document.querySelectorAll('.classone, .class1')

elements.forEach(function (element) {
  element.classList.add('newclass')
})

There are some detailed examples as well as notes on browser compatibility in the MDN article on node lists.

(whoops, ninja'd) :-)


#18

Yes I noticed that IE11 doesn't support forEach which is why I went with the older loop method :slight_smile: (Mind you I only knew that because I had to look it all up anyway).


#19

Yeah, and the Array.prototype.forEach.call() solution is indeed somewhat... er, awkward. ^^ However there's actually a super simple polyfill:

NodeList.prototype.forEach = NodeList.prototype.forEach 
  || Array.prototype.forEach

#20

This is a very good discussion. Perhaps I feel that the title is not the most suitable one. Can you please help me to change it to the most suitable title so that others can search it in the future.

Also, In this example →

var select = document.querySelector('select') // use more specific selector here
var classOne = document.querySelector('.classone')

select.addEventListener('change', function (event) {
  if (event.target.value === 'condition_2') {
    classOne.classList.add('newclass')
  }
})

when we choose the condition 1 again the extra class that we are injecting should be deleted. How to accomplish this?


#21

I have one more question →

<select class="video_home_flex_select">
        <option value="condition_1">Condition 1</option>
        <option value="condition_2" selected="selected">Condition 2</option>
        <option value="condition_3">Condition 3</option>
</select>

By default, I have selected condition 2, for example, but it doesn't work → I mean the class associated with that condition doesn't get implemented. I think we need to tie this to some script.