node.jsejstimeago

How to use packages in EJS template?


I'm trying to use timeago.js in an EJS template. I have tried to export the library like this:

src/lib/lib.js

 const timeago = require('timeago.js');
    exports.index = function(req, res){
        res.render('links/list',{timeago: timeago});
    }

The route is: routes/links.js

router.get('/', (req, res)=>{
        sequelize.query('SELECT * FROM links', {
            type: sequelize.QueryTypes.SELECT
        }).then((links)=>{
            res.render('links/list', {links: links});
        });
    });

The EJS template is: views/links/list.ejs

<div class="container p-4">
     <div class="row">
         <% for(i of links){ %>
             <div class="col-md-3">
                 <div class="card text-center">
                     <div class="card-body">
                         <a target="_blank" href="<%= i.url %>">
                             <h3 class="card-title text-uppercase"><%= i.title %></h3>
                         </a>
                         <p class="m-2"><%= i.description %></p>
                         <h1><%= timeago.format(i.created_at); %></h1>
                         <a href="" class="btn btn-danger">Delete Link</a>
                         <a href="" class="btn btn-secondary">Edit</a>
                     </div>
                 </div>
             </div>
     <% } %>

I need to use the library in the h1 to transform a timestamp I got from the database. However, I always get the same error: timeago is not defined.

How could I export Timeago correctly to use in EJS template? If I require the library in the routes file and send it to the EJS template through an object works perfectly, but not when I export it from another file.


Solution

  • I made the following test program to do a minimal test of timeago.js

    const ejs = require('ejs');
    const timeago = require('timeago.js');
    
    let template = `
    <% for(i of links){ %>
        <h1> <%- i.created_at %>: <%- timeago.format(i.created_at) %> </h1>
    <% } %>
    `;
    
    const renderData = {
        links: [
            {
                created_at: new Date()
            }
        ],
        timeago
    };
    const output = ejs.render(template, renderData);
    
    console.log(output);
    

    Output:

    <h1> Mon Sep 07 2020 00:01:57 GMT-0700 (Pacific Daylight Time): just now </h1>
    

    So as long as you correctly pass the timeago object into your rendering data it will work.

    The problem is likely here:

    router.get('/', (req, res)=>{
            sequelize.query('SELECT * FROM links', {
                type: sequelize.QueryTypes.SELECT
            }).then((links)=>{
                res.render('links/list', {links: links});
            });
        });
    

    Where you are not passing in the timeago object. This line:

    res.render('links/list', {links: links});
    

    Should probably be:

    res.render('links/list', {links: links, timeago});
    

    Edit:

    More complete example using file paths specified in comments:

    routes/links.js:

    var express = require('express')
    var router = express.Router();
    
    const lib = require("../src/lib/lib");
    
    router.get('/', (req, res)=>{
        lib.index(req, res);
    });
    
    module.exports = router;
    

    src/lib/lib.js

    const timeago = require('timeago.js');
    
    exports.index = function(req, res) {
        const links = [
            {
                created_at: new Date()
            }
        ];
        res.render('links/list',{ timeago, links });
    }