-3

I have an accordion bootstrap component in one of my designs. I have added a down carot from font awesome and when the accordion expands I want to add a class of "rotate" to that carot so it points up. Then when the accordion collapse, I want the carot to point down again. The code works on the first down carot but not on the rest of them. How can I make it so the class will apply to whichever one the user clicks on?

Here is the HTML

        <div class="accordion my-5" id="accordionExample">
          <div class="card" data-toggle="collapse" data-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
            <div class="card-header d-flex" id="headingOne">
              <h2 class="mb-0">
                <button class="btn" type="button">
                  question 1
                </button>
              </h2>
              <i class="fas fa-caret-down" style="margin-left:auto; padding:12px 10px 0 0;"></i>
            </div>
            <div id="collapseOne" class="collapse show" aria-labelledby="headingOne" data-parent="#accordionExample">
              <div class="card-body">
                Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed id tellus urna. 
              </div>
            </div>
          </div>
          <div class="card" type="button" data-toggle="collapse" data-target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
            <div class="card-header d-flex" id="headingTwo">
              <h2 class="mb-0">
                <button class="btn collapsed" type="button" data-toggle="collapse" data-target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
                  question 2
                </button>
              </h2>
              <i class="fas fa-caret-down" style="margin-left:auto; padding:12px 10px 0 0;"></i>
            </div>
            <div id="collapseTwo" class="collapse" aria-labelledby="headingTwo" data-parent="#accordionExample">
              <div class="card-body">
                Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed id tellus urna.
              </div>
            </div>
          </div>
          <div class="card" type="button" data-toggle="collapse" data-target="#collapseThree" aria-expanded="false" aria-controls="collapseThree">
            <div class="card-header d-flex" id="headingThree">
              <h2 class="mb-0">
                <button class="btn collapsed" type="button" data-toggle="collapse" data-target="#collapseThree" aria-expanded="false" aria-controls="collapseThree">
                  question 3
                </button>
              </h2>
              <i class="fas fa-caret-down" style="margin-left:auto; padding:12px 10px 0 0;"></i>
            </div>
            <div id="collapseThree" class="collapse" aria-labelledby="headingThree" data-parent="#accordionExample">
              <div class="card-body">
                Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed id tellus urna.
              </div>
            </div>
          </div>
          <div class="card" type="button" data-toggle="collapse" data-target="#collapseThree" aria-expanded="false" aria-controls="collapseThree">
            <div class="card-header d-flex" id="headingFour">
              <h2 class="mb-0">
                <button class="btn collapsed" type="button" data-toggle="collapse" data-target="#collapseThree" aria-expanded="false" aria-controls="collapseThree">
                  question 4
                </button>
              </h2>
              <i class="fas fa-caret-down" style="margin-left:auto; padding:12px 10px 0 0;"></i>
            </div>
            <div id="collapseFour" class="collapse" aria-labelledby="headingThree" data-parent="#accordionExample">
              <div class="card-body">
                Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed id tellus urna.
              </div>
            </div>
          </div>
        </div>

Here is the Javascript:

var carotDown = document.querySelector('.fa-caret-down');

carotDown.addEventListener('click', function(e){
  e.target.classList.toggle('rotate');
});

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
bsmith
  • 103
  • 3
  • 10
  • 1
    *"The Document method [`querySelector()`](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector) returns **the first Element** within the document that matches the specified selector."* You're looking for [`querySelectorAll`](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll). – Herohtar Oct 01 '19 at 21:32
  • I updated it to querySelectorAll and now none of them work. – bsmith Oct 01 '19 at 21:37
  • Did you look at the example on the querySelectorAll page? You will need to use `forEach` on the results to apply the handler to the individual items. – Herohtar Oct 01 '19 at 21:38
  • you beat me to it! I was just about to comment that. Let me try that real quick. I'm sure thats the issue. – bsmith Oct 01 '19 at 21:40
  • https://stackoverflow.com/questions/10693845/what-do-queryselectorall-and-getelementsby-methods-return – epascarello Oct 01 '19 at 21:41

1 Answers1

0

As stated in the comments, querySelector() returns the first match it can find. If you use querySelectorAll(), it will return a collection of all matching elements, but that being the case, you'd then need to loop over the collection and bind each element one at a time.

Another option is to continue to use querySelector(), but to find an ancestor of all the actual elements that you want to bind and instead of binding each of those, just bind an event to the ancestor. Then, when any descendant is clicked, the event will bubble to the ancestor and you can handle it there using event.target to determine exactly which element triggered the event in the first place. This is called "Event Delegation".

// Set the event on an ancestor
document.querySelector('.accordion').addEventListener('click', function(e){
  // Check to see if the event was triggered by an element you care about
  if(e.target.classList.contains("fa-caret-down")){
    e.target.classList.toggle('rotate'); // Work with the element that triggered the event.
  }
});
.rotate { color:red; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<div class="accordion my-5" id="accordionExample">
          <div class="card" data-toggle="collapse" data-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
            <div class="card-header d-flex" id="headingOne">
              <h2 class="mb-0">
                <button class="btn" type="button">
                  question 1
                </button>
              </h2>
              <i class="fas fa-caret-down" style="margin-left:auto; padding:12px 10px 0 0;">**</i>
            </div>
            <div id="collapseOne" class="collapse show" aria-labelledby="headingOne" data-parent="#accordionExample">
              <div class="card-body">
                Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed id tellus urna. 
              </div>
            </div>
          </div>
          <div class="card" type="button" data-toggle="collapse" data-target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
            <div class="card-header d-flex" id="headingTwo">
              <h2 class="mb-0">
                <button class="btn collapsed" type="button" data-toggle="collapse" data-target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
                  question 2
                </button>
              </h2>
              <i class="fas fa-caret-down" style="margin-left:auto; padding:12px 10px 0 0;">**</i>
            </div>
            <div id="collapseTwo" class="collapse" aria-labelledby="headingTwo" data-parent="#accordionExample">
              <div class="card-body">
                Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed id tellus urna.
              </div>
            </div>
          </div>
          <div class="card" type="button" data-toggle="collapse" data-target="#collapseThree" aria-expanded="false" aria-controls="collapseThree">
            <div class="card-header d-flex" id="headingThree">
              <h2 class="mb-0">
                <button class="btn collapsed" type="button" data-toggle="collapse" data-target="#collapseThree" aria-expanded="false" aria-controls="collapseThree">
                  question 3
                </button>
              </h2>
              <i class="fas fa-caret-down" style="margin-left:auto; padding:12px 10px 0 0;">**</i>
            </div>
            <div id="collapseThree" class="collapse" aria-labelledby="headingThree" data-parent="#accordionExample">
              <div class="card-body">
                Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed id tellus urna.
              </div>
            </div>
          </div>
          <div class="card" type="button" data-toggle="collapse" data-target="#collapseThree" aria-expanded="false" aria-controls="collapseThree">
            <div class="card-header d-flex" id="headingFour">
              <h2 class="mb-0">
                <button class="btn collapsed" type="button" data-toggle="collapse" data-target="#collapseThree" aria-expanded="false" aria-controls="collapseThree">
                  question 4
                </button>
              </h2>
              <i class="fas fa-caret-down" style="margin-left:auto; padding:12px 10px 0 0;">**</i>
            </div>
            <div id="collapseFour" class="collapse" aria-labelledby="headingThree" data-parent="#accordionExample">
              <div class="card-body">
                Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed id tellus urna.
              </div>
            </div>
          </div>
        </div>
        
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71