How to fix your EJS modals when they don’t show the correct info

How to fix your EJS modals when they don’t show the correct info

Does your EJS page behave incorrectly? You click on a button to open a modal only to find out it shows the wrong text? You’re getting crazy if you don’t find a solution any time soon and Stackoverflow couldn’t help you. We’ve all been there. The code looks ok but the behaviour is super strange and you really can’t explain why.

When you’re displaying a list of items in EJS, or any other template engine for that matter, there’s one thing to be aware of:

All id attributes inside HTML elements need to have unique values

This is a general requirement on all HTML pages. The purpose of the id attribute is to uniquely identify the element it belongs to when linking, scripting or styling.

Let’s say we have a table with a couple of users. Inside each row there’s an action button that opens up a modal which shows info of that particular user and allows editing some fields. You would think to write something like this:

<% users.forEach((user) => { %>
<tr>
  <td><%= user._id %></td>
  <td><%= user.name %></td>
  <td><%= user.dateOfBirth %></td>
  <td><%= user.knownFor %></td>
  <td>
    <button type="submit" data-target="#modal-edit-user"> <!-- 🚫 all buttons link to first modal -->
      Edit
    </button>
  </td>
</tr>

<div id="modal-edit-user"> <!-- 🚫 multiple modals with same id -->
  <!-- Modal content -->
</div>
<% }) %>

The problem here is that for each user in the array you create a modal that has the same id as all the other ones. The browser looks at the first modal and disregards the others with duplicate id resulting in all buttons linking to the first modal. Which explains the strange behaviour we see.

To fix this we need to make the id of each modal unique. Usually you choose a property that is unique to each item inside the array and append it to the id attribute. In our case our user has a unique identifier from the database. You can also choose the index of the item in the array or put together two properties to create a unique combination.

Also to make sure we link each button to the correct modal we also change the data-target* attribute in the same way.

*This is an attribute specific to the Bootstrap CSS framework which adds the relevant JavaScript event handlers to buttons and modals and bind them together. You can read more about it here https://getbootstrap.com/docs/4.0/components/modal/#via-data-attributes

<% users.forEach((user) => { %>
<tr>
  <td><%= user._id %></td>
  <td><%= user.name %></td>
  <td><%= user.dateOfBirth %></td>
  <td><%= user.knownFor %></td>
  <td>
    <button type="submit" data-target="#modal-edit-user-<%= user._id %>"> <!-- ✅ each buttons links to its corresponding modal -->
      Edit
    </button>
  </td>
</tr>

<div id="modal-edit-user-<%= user._id %>"> <!-- ✅ unique id for each modal -->
  <!-- Modal content -->
</div>
<% }) %>

Now our buttons link to their specific modal which shows the correct info for each user. No weird behaviour anymore. Everything works as it should!

Join my Newsletter

Was this article helpful? Subscribe to get my next content in your email.

Leave a Reply