Skip to content

Control Flow Logic

The output tags (<%= %>) handle display, but true dynamism requires logic. To conditionally render content or iterate over data collections, EJS uses “Scriptlet” tags (<% %>) that allow you to execute standard JavaScript code inside your views.

Scriptlet tags accept standard JavaScript syntax. Unlike output tags, they do not print their result to the page; they are used strictly for control flow operations like loops and if-statements.

To render a list of items, we break a standard JavaScript for loop across multiple lines of HTML. The opening bracket { lives in the first scriptlet, and the closing bracket } lives in its own scriptlet at the end.

<ul>
<% things.forEach(thing => { %>
<li>
<a href="/things/<%= thing.id %>" style="color: inherit; text-decoration: none; display: block; width: 100%;">
<%= thing.name %>
</a>
</li>
<% }) %>
</ul>

Scriptlets allow you to perform presence checks or alter the output based on data states. This pattern handles scenarios like “Empty States” or access control.

<% if (things.length === 0) { %>
<!-- Rendered if the condition is true -->
<div class="alert">Nothing found in the database.</div>
<% } else { %>
<!-- Rendered if the condition is false -->
<ul>
<% things.forEach((thing) => { %>
<li><%= thing.name %></li>
<!-- conditional output -->
<% if (!thing.active) { %> (Inactive) <% } %>
<% }) %>
</ul>
<% } %>

Note that we can use any valid JavaScript, including Array methods like .forEach(), which are often cleaner than standard for loops in templates.

⏭ Code Comments

Logic requires documentation. Let’s see how to add comments that don’t leak to the client.