Skip to content

Latest commit

 

History

History
195 lines (154 loc) · 7.26 KB

File metadata and controls

195 lines (154 loc) · 7.26 KB

The Absolute Basics

Every EJS journey starts with those magical <% %> tags. These are the portals where JavaScript comes alive in your HTML.

  • The EJS Tag Types: EJS uses special tags to embed JavaScript logic and data into HTML.

    • <%%>: Raw Output (Escape HTML Characters) This is the most common tag for displaying data. It automatically escapes HTML characters (like < to &lt;) to prevent XSS attacks. Always use this for displaying user-provided data!

      <h1>Hello, <%= user.name %>!</h1>
      <p>You have <%= item_count %> items in your cart.</p>
    • <%- %>: Unescaped Raw Output (Use with Caution!) This tag outputs the raw, unescaped HTML. Only use this if you are absolutely sure the data you're injecting is safe HTML (e.g., Markdown rendered by a trusted library, or HTML generated by your own server).

      <article>
        <%- post.content %>
      </article>

      Pro-Tip: If you're rendering Markdown on the server and want it as HTML, this is what you'd use after the Markdown converter.

    • < selfless % >: Scripting Tag (No Output) This tag executes JavaScript code but doesn't output anything to the HTML.

      <%
        let greeting = "Welcome back!";
        if (user.isAdmin) {
          greeting = "Welcome, Admin!";
        }
      %>
      <h1><%= greeting %></h1>
    • <%- include('partial', { data: value }) %>: Including Partials This is a special instruction for including other EJS files (partials) within the current template. Great for reusing headers, footers, navigation, etc. Data passed to the include is available in the partial.

      <!DOCTYPE html>
      <html>
      <head>
        <title><%= title %></title>
      </head>
      <body>
        <%- include('header') %> <main>
          <%- body %> </main>
        <%- include('footer', { year: new Date().getFullYear() }) %>
      </body>
      </html>

      Remember: body in the example above is a common variable name when rendering layouts (e.g., in Express, you'd render res.render('layout', { body: '<your-page-html>' })).


Data & Logic

  • Accessing Data: Variables passed from server-side code (e.g., an Express res.render('template', { user: user, products: products })) are directly accessible within the EJS template.

    <h2>Product List</h2>
    <ul>
      <% products.forEach(function(product) { %>
        <li><%= product.name %> - $<%= product.price.toFixed(2) %></li>
      <% }); %>
    </ul>
  • Conditional Rendering (if/else): Hide or show parts of your HTML based on conditions.

    <% if (user.isLoggedIn) { %>
      <p>Welcome back, <%= user.name %>!</p>
      <a href="/logout">Logout</a>
    <% } else { %>
      <p>Please log in.</p>
      <a href="/login">Login</a>
    <% } %>
  • Loops (forEach, for): Render lists of items dynamically. forEach is often cleaner for arrays.

    <h3>Users:</h3>
    <ul>
      <% users.forEach(function(user) { %>
        <li>ID: <%= user.id %>, Name: <%= user.name %></li>
      <% }); %>
    </ul>
    
    <% for (let i = 0; i < messages.length; i++) { %>
      <p>Message <%= i + 1 %>: <%= messages[i] %></p>
    <% } %>
  • Variable Declaration within Templates: You can declare and manipulate variables directly in your EJS using the scripting tag.

    <% let total = 0; %>
    <% items.forEach(function(item) {
        total += item.price * item.quantity;
    }); %>
    <p>Total Order: $<%= total.toFixed(2) %></p>

EJS Configuration

While EJS itself is just a templating engine, it'll always be used with a web framework like Express.js.

  • Setting up EJS with Express:

    // app.js (or server.js)
    const express = require('express');
    const app = express();
    const path = require('path');
    
    // Set the view engine to EJS
    app.set('view engine', 'ejs');
    
    // Specify the directory where your EJS template files are located
    app.set('views', path.join(__dirname, 'views'));
    
    // Example route
    app.get('/', (req, res) => {
      const userData = {
        name: "Dev Gopher",
        isLoggedIn: true,
        isAdmin: false,
        item_count: 5,
        products: [
          { name: "Laptop", price: 1200 },
          { name: "Mouse", price: 25 }
        ],
        messages: ["Hello!", "How are you?"]
      };
      res.render('index', userData); // Renders 'views/index.ejs' with userData
    });
    
    app.get('/admin', (req, res) => {
      const adminUser = { name: "Admin", isLoggedIn: true, isAdmin: true };
      res.render('admin-dashboard', { user: adminUser, title: 'Admin Dashboard' });
    });
    
    const PORT = process.env.PORT || 3000;
    app.listen(PORT, () => {
      console.log(`Server running on port ${PORT}`);
    });
  • _layout.ejs: EJS doesn't have a built-in layout system like some other engines, a common pattern is to create a _layout.ejs (or layout.ejs) file and pass the rendered content of your specific page into it.

    // In an Express route:
    const ejs = require('ejs'); // You might need to directly require ejs for this pattern
    
    app.get('/mypage', async (req, res) => {
      const pageData = { title: 'My Awesome Page', content: 'This is the page content!' };
      const pageHtml = await ejs.renderFile(path.join(__dirname, 'views', 'mypage.ejs'), pageData, { async: true });
    
      res.render('layout', {
        title: pageData.title, // Pass title to layout
        body: pageHtml       // Pass the rendered page content as 'body'
      });
    });

    (Then, in layout.ejs, you'd use <%- body %> as shown in the include example above.)


Additional Tips and Tricks!

  • Security First: Always, always use <%= %> for displaying user-generated content to prevent XSS. Only use <%- %> when you are certain the content is safe HTML.
  • Keep Logic Light: While you can write complex JavaScript in EJS, it's generally best practice to keep your templates as "dumb" as possible. Prepare your data in your server-side routes/controllers and pass well-structured objects to EJS. Templates should primarily focus on displaying that data.
  • Error Handling: By default, if there's a JavaScript error in your EJS, it will throw an error and likely crash your server (depending on your setup). Use try...catch blocks in your server-side routes to gracefully handle rendering errors.
  • Whitespace Control: EJS can sometimes output extra whitespace due to the JS tags. If this is an issue, you can trim whitespace:
    • <%= user.name -%> (trims whitespace after the tag)
    • <%- user.name %>
    • <%- include('partial') -%>
    • You can also configure EJS to have a global rmWhitespace: true option in some frameworks.
  • Debugging: console.log() works inside <% %> tags! Your output will appear in your server's console.
  • Partials are Your Friends: Break down large templates into smaller, reusable partials (e.g., _header.ejs, _footer.ejs, _nav.ejs). This makes your code cleaner and easier to maintain.