Skip to content

How to Fix Your EJS Modals When They Don't Show the Correct Info

2 min read

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!

Write clean code. Stay ahead of the curve.

Every other Tuesday, I share tips on how to build robust Node.js applications. Join a community of 1,423 developers committed to advancing their careers and gain the knowledge & skills you need to succeed.

No spam! 🙅🏻‍♀️ Unsubscribe at any time.

You might also like

Logging with Pino and AsyncLocalStorage in Node.js

From a lousy dump of debug statements to a powerful debugging tool. Learn how to apply contextual logging in Node.js.
Read article

Should You Use char, varchar, or text in PostgreSQL?

What are the differences between char, varchar, and text in PostgreSQL, and which one should you choose?
Read article

6 Common Sequelize Queries Explained in SQL

Writing SQL queries can be daunting. We'll unveil the magic by translating 6 common Sequelize queries into raw SQL.
Read article