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.
<% 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!