Loading

Quipoin Menu

Learn • Practice • Grow

express-js / Express.js Serving Dynamic Content
tutorial

Express.js Serving Dynamic Content

Now that you know how to set up templating engines, let's explore how to serve truly **dynamic content** – pages that change based on user input, database data, or application state. This is where templating engines shine.

Passing Data to Templates

The `res.render()` method accepts a data object as its second parameter. This data becomes available in your template.
app.get('/profile/:id', async (req, res) => {
  const userId = req.params.id;
  const user = await getUserFromDatabase(userId);
 
  res.render('profile', {
    user: user,
    title: `Profile - ${user.name}`,
    isLoggedIn: req.session.user ? true : false
  });
});

Dynamic Content Examples with EJS

1. Conditional Rendering
<div>
  <% if (user) { %>
    <h1>Welcome, <%= user.name %>!</h1>
    <a href="/logout">Logout</a>
  <% } else { %>
    <h1>Welcome, Guest!</h1>
    <a href="/login">Login</a>
  <% } %>
</div>

2. Looping Through Data
<h2>Product List</h2>
<ul>
  <% products.forEach(product => { %>
    <li>
      <h3><%= product.name %></h3>
      <p>Price: $<%= product.price %></p>
      <% if (product.inStock) { %>
        <button>Add to Cart</button>
      <% } else { %>
        <span class="out-of-stock">Out of Stock</span>
      <% } %>
    </li>
  <% }) %>
</ul>

3. Using Partials (Reusable Components)

Create a header partial: `views/partials/header.ejs`
<header>
  <nav>
    <a href="/">Home</a>
    <a href="/products">Products</a>
    <a href="/about">About</a>
    <% if (user) { %>
      <span>Welcome, <%= user.name %>!</span>
    <% } %>
  </nav>
</header>

Use it in your main template:
<!DOCTYPE html>
<html>
<head>
  <title><%= title %></title>
</head>
<body>
  <% include partials/header %>
 
  <main>
    <h1><%= pageTitle %></h1>
    <%= content %>
  </main>
</body>
</html>

Real-World Example: Blog Post Page

<!-- Route -->
app.get('/post/:slug', async (req, res) => {
  const post = await getPostBySlug(req.params.slug);
  const comments = await getCommentsForPost(post.id);
 
  res.render('post', {
    post: post,
    comments: comments,
    user: req.session.user,
    title: post.title,
    metaDescription: post.excerpt
  });
});
<!-- views/post.ejs -->
<!DOCTYPE html>
<html>
<head>
  <title><%= post.title %></title>
  <meta name="description" content="<%= post.excerpt %>">
</head>
<body>
  <% include partials/header %>
 
  <article>
    <h1><%= post.title %></h1>
    <div class="meta">
      By <%= post.author %> on <%= post.date.toLocaleDateString() %>
    </div>
    <div class="content">
      <%- post.content %> <!-- Use unescaped output for HTML content -->
    </div>
  </article>
 
  <section class="comments">
    <h2>Comments<%= comments.length ? ` (${comments.length})` : '' %></h2>
   
    <% if (comments.length === 0) { %>
      <p>No comments yet. Be the first to comment!</p>
    <% } else { %>
      <% comments.forEach(comment => { %>
        <div class="comment">
          <strong><%= comment.author %></strong>
          <p><%= comment.text %></p>
          <small><%= comment.date.toLocaleString() %></small>
        </div>
      <% }); %>
    <% } %>
  </section>
 
  <% if (user) { %>
    <form action="/post/<%= post.slug %>/comment" method="POST">
      <textarea name="comment" placeholder="Add a comment..."></textarea>
      <button type="submit">Post Comment</button>
    </form>
  <% } %>
</body>
</html>

Two Minute Drill

  • Pass data to templates as the second argument to `res.render()`.
  • Use conditionals (`if/else`) to show/hide content based on data.
  • Loop through arrays with `forEach` to display lists.
  • Create reusable partials with `include` to avoid code duplication.
  • Be careful with unescaped output (`<%- %>`) – only use for trusted content.

Need more clarification?

Drop us an email at career@quipoinfotech.com