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
