handlebars and js: assigning different id values inside for loop and referencing them outside the loop

In my webpage I am populating a table using handlebars and getting the values from a db:

<table>
  <tbody id="myDiv">
  {{# each alarms}}
    <tr class="row100 body">
      <td class="cell100 column1"><a href="#" id="btn_exp">{{ this.alm_id }}</a></td>
      <td class="cell100 column2><a href="#">{{ this.message }}</a></td>
      <td class="cell100 column3"><a href="#">{{ this.level }}</a></td>
    </tr>
  {{/each}}
  </tbody>
</table>

Now I want that rows to be clickable and to open a particular popup depending on the row (there will be a description of that row).

So I wrote this:

<script>
  var modal_exp = document.getElementById('myModal_explanatory');
  var btn_exp = document.getElementById("myBtn_exp");
  var span_exp = document.getElementById("close_exp");

  btn_exp.onclick = function() { modal_exp.style.display = "block"; }
  span_exp.onclick = function() { modal_exp.style.display = "none"; }

  window.onclick = function(event) {
    if (event.target == modal_exp) { modal_exp.style.display = "none"; }
  }
</script>

The popup works well when called outside the table. Inside the table it doesn't work and the problem is that I'm assigning the same id to every row and it doesn't know which one is referring to.

I have no idea how to solve this. The idea is to have a different id for every row (that can be achieved using handlebars, e.g. id="myBtn-{{this.id}}" but then I don't understand how to assign it to my bin_exp variable inside the script.

1 answer

  • answered 2019-05-16 14:46 Nick Lediet

    An approach using classes would work much better over IDs. Classes are a great way to apply an identifier to similar elements. In this case you need a way to apply a click event to multiple btn-exp.

    To pass the data to the element, leverage to data attribute on the element. You can pass what ever data from handle bars you need into the attribute an later access in JavaScript.

    <table>
      <tbody id="myDiv">
      {{# each alarms}}
        <tr class="row100 body">
          <td class="cell100 column1">
            <!-- Class will be used to select all .btn_exp and from their events you can access the unique data -->
            <a href="#" class="btn_exp" data-alm-id="{{this.alm_id}}">
                {{ this.alm_id }}
                </a>
           </td>
          <td class="cell100 column2><a href="#">{{ this.message }}</a></td>
          <td class="cell100 column3"><a href="#">{{ this.level }}</a></td>
        </tr>
      {{/each}}
      </tbody>
    </table>
    
      var modal_exp = document.getElementById('myModal_explanatory');
      var btn_exp = document.querySelectoryAll('.btn_exp'); // This returns a NodeList of the .btn_exp objects
      var span_exp = document.getElementById("close_exp");
    
      span_exp.onclick = function() { modal_exp.style.display = "none"; }
    
      btn_exp.forEach(function(button) {
        button.addEventListener('click', function(event) {
          // Through the event object you can get the unique instance of .btn_exp that you clicked
          var button = event.currentTarget
    
          modal_exp.style.display = "block";
    
          // If you wanted to get the data-alm-id value for this specific button you can access it like this
          var button_alm_id = button.dataset.almId // dashes are converted to Camel case 
          // ... Do what ever you want with this value 
        });
      });
    

    For more info on querySelector() and querySelectorAll() checkout the MDN here https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector