Search code examples
javascriptdombootstrap-4event-listener

JavaScript Event Listeners interacting with hidden DOM Elements


I'm creating a travel reimbursement form for work. We have 4 separate types of travel, so my plan was to have a button for each type, and when you click on the button the correct form appears within it's own <section> element. I'm using Bootstrap 4, and I have each form on my index.html file with a class of "d-none" so that none display on load.

In the mileage section of the form, I have a Font-Awesome plus and minus sign to add another row or delete a row. The problem I'm running in to is that my event listeners work fine with the first form listed in index.html. But it doesn't work at all on the second form.

Each form has a class of ".mileage-form". I know that you can't have separate HTML elements with the same ID, but I thought classes were ok. I know I can fix this issue by having the HTML rendered with JavaScript when the correct form button is clicked, instead of just unhiding the html, but I'm trying to understand WHY what I'm trying doesn't work.

The index.html looks as follows:

<!----------------------------- ITINERANT TRAVEL ----------------------------->
    <section id="itinerant" class="d-none">
      <form class="mileage-form">
        <div class="form-group form-row justify-content-center" id="row-1">
             <div class="col-sm-2 col-md-1">
               <label for="date-1">Date</label>
               <input type="date" id="date-1" class="form-control">
             </div>
             <div class="col-sm-3 col-md-3">
               <label for="origin-1">Origin Address</label>
               <input type="text" class="form-control" id="origin-1" placeholder="Street Address, City, State, Zip">
             </div>
             <div class="col-sm-3 col-md-3">
               <label for="destination-1">Destination Address</label>
               <input type="text" class="form-control" id="destination-1" placeholder="Street Address, City, State, Zip">
             </div>
             <div class="col-sm-2 col-md-1">
               <label for="personal-1">Personal Miles</label>
               <input type="text" class="form-control" id="personal-1" placeholder="0">
             </div>
             <div class="col-sm-2 col-md-1">
               <label for="calculated-1">Calculated Miles</label>
               <input type="text" class="form-control" id="calculated-1" placeholder="0" value="" disabled>
             </div>
          </div>
      </form>
      <div class="form-group form-row justify-content-center">
        <a href='#'><i class="fa fa-plus add-row" style="color: blue;"></i></a>
        <a href='#'><i class="fa fa-minus delete-row" style="color: red;"></i></a>
      </div>
      <div class="form-group form-row justify-content-center">
        <button type="button" class="btn btn-outline-success" id="calculate-mileage">Calculate Mileage</button>
        <button type="button" class="btn btn-outline-danger" id="clear-all">Clear All</button>
      </div>
    </section>

<!-------------------- Single Day Travel ----------------------->
    <section id="single-day" class="d-none">
      <form class="mileage-form">
        <div class="form-group form-row justify-content-center" id="row-101">
          <div class="col-sm-2 col-md-1">
            <label for="date-101">Date</label>
            <input type="date" id="date-101" class="form-control">
          </div>
          <div class="col-sm-3 col-md-3">
            <label for="origin-101">Origin Address</label>
            <input type="text" class="form-control" id="origin-101" placeholder="Street Address, City, State, Zip">
          </div>
          <div class="col-sm-3 col-md-3">
            <label for="destination-101">Destination Address</label>
            <input type="text" class="form-control" id="destination-101" placeholder="Street Address, City, State, Zip">
          </div>
          <div class="col-sm-2 col-md-1">
            <label for="personal-101">Personal Miles</label>
            <input type="text" class="form-control" id="personal-101" placeholder="0">
          </div>
          <div class="col-sm-2 col-md-1">
            <label for="calculated-101">Calculated Miles</label>
            <input type="text" class="form-control" id="calculated-101" placeholder="0" value="" disabled>
          </div>
        </div>
    </form>
      <div class="form-group form-row justify-content-center">
        <a href='#'><i class="fa fa-plus add-row" style="color: blue;"></i></a>
        <a href='#'><i class="fa fa-minus delete-row" style="color: red;"></i></a>
      </div>
</section>

And my event listeners look like this:

document.querySelector('.add-row').addEventListener('click', mileage.addRow);
document.querySelector('.delete-row').addEventListener('click', mileage.deleteRow);

The functions to add and delete a row are in a Mileage Class, but I don't think there is a problem there, because they do function properly with the "Itinerant" section. And if I comment the "Itinerant" section out, they work fine with the "Single Day" section. But like I said, if both sections are uncommented, and just hidden, they only work with the Itinerant section. If you want to see that code though, I have it all on github, and they would be in the mileage.js file.

I would greatly appreciate any explanation on what I did wrong!


Solution

  • use

       querySelectorAll(".add-row").forEach(function(item){ item.addEventListener .. etc }):
    

    to target all of the elements