How to use node modules (like MomentJS) in EJS views?
Asked Answered
T

11

54

To use MomentJS in views/custom.ejs, what is the correct way (if any)?

  1. Server side

    routes/index etc we can easily use require('moment'); etc and it works fine.

  2. Server Side (EJS views)

    views/custome.ejs, something like <% var m = require('moment'); %> doesn't work

I am using ExpressJS with EJS as the template engine.

Tchad answered 9/10, 2012 at 7:24 Comment(0)
I
77

I found another way of doing this, and I think it has some advantages.

  • Don't polute your code exporting filters.
  • Access any method without the need to export them all.
  • Better ejs usage (no | pipes).

On your controller, or view.js do this:

var moment = require('moment');
exports.index = function(req, res) {
    // send moment to your ejs
    res.render('index', { moment: moment });
}

Now you can use moment inside your ejs:

<html>
    <h1><%= moment().fromNow() %></h1>
</html>

I'm not an Node expert, so if anyone see something bad on doing this, let me know! :)

Iridissa answered 29/8, 2013 at 1:20 Comment(2)
That's the most flexible way IMODepicture
Works perfect, just need to organize sending all the extra libs to the template.Abeokuta
S
34

One more option:

This way you are setting the moment variable to a local available to all scripts in any EJS page on your site.

In your "index.js" (or "app.js") file do this: (after you have set up your 'app' with Express)

var moment = require('moment');
var shortDateFormat = "ddd @ h:mmA"; // this is just an example of storing a date format once so you can change it in one place and have it propagate
app.locals.moment = moment; // this makes moment available as a variable in every EJS page
app.locals.shortDateFormat = shortDateFormat;

Then in your EJS file you can refer to moment (and shortDateFormat) as variables like this:

<%= moment(Date()).format(shortDateFormat) %>

Perhaps this is slightly more elegant?

Stereo answered 3/11, 2014 at 6:7 Comment(3)
the cleanest solution!Sceptic
Any specific reason to put it in app.locals instead of using res.locals for passing moment to a particular view only?Clyde
Not that I can recall! I haven't worked on this for a long time. :-)Stereo
E
23
var moment = require('moment');
app.locals.moment = moment;

Use in the view:

<%= moment(myDateValue).fromNow() %>

Now you can simply use moment in your EJS files.

Eclogue answered 2/6, 2017 at 2:43 Comment(0)
D
11

I use moment on the server side with ejs. I wrote an ejs filter function that will return fromNow.

npm install moment

./views/page.ejs

<span class="created_at"><%=: item.created_at | fromNow %></span>

./routes/page.js

var ejs = require('ejs')
  , moment = require('moment');

ejs.filters.fromNow = function(date){
  return moment(date).fromNow()
}
Disaccharide answered 9/10, 2012 at 8:5 Comment(1)
it could probably be more flexible if you exported moment(date) rather than a function. Might work, I haven't tried | moment.fromNowDisaccharide
E
3

You can create the function and attach it to the app.locals. and use it in the ejs template on the server side.

In your routes file you do

../routes/page.js

var ejs = require('ejs')
  , moment = require('moment');

app.locals.fromNow = function(date){
  return moment(date).fromNow();
}

../views/page.ejs

<span class="created_at"><%= fromNow(item.created_at) %></span>

Just remember to have moment added to to your package.json file

Enphytotic answered 2/4, 2013 at 15:53 Comment(1)
I like this better since it will only link the ejs with the function, and not with the modules.Preface
C
3

How about passing down require like this:

res.render('index', { require: require });

You might need to tweak to maintain the path:

res.render('index', { require: module => require(module /* here you may insert path correction */) });

Obviously this works with Node (backend) only.

Conduction answered 19/6, 2017 at 14:7 Comment(2)
This looks like the only real answer to the question. Nice work. Will need to try this out.Burmeister
I was able to get this working in this repo: github.com/chriscalo/ejs-require. Really satisfying solution. Not sure why EJS templates don't work this way out of the box.Burmeister
C
0

The server side (EJS views) which you mentioned above is running on browser and not on your server. You cannot use require because browsers cannot understand it. You need to import the moment.js to use it

<script src="/js/moment.min.js"></script>
Coventry answered 9/10, 2012 at 7:47 Comment(3)
Thanks @Coventry I am now looking at rendered code (browser side) and my Layout.ejs includes: <script type="text/javascript" src="javascripts/moment.min.js"></script> custom.ejs (view) has code using momentJS lib, example var a = moment(new Date()); Here a is found to be null.Tchad
Check this link to see how to use it - https://mcmap.net/q/339688/-how-to-use-moment-jsCoventry
From my understanding, '<% ... %>' and '<%= ... %>' enclosed code is ran/rendered on the server side, not on the client side. Client just gets the rendered (processed) results as plain html, unless you are explicitly using <script></script> tag, which will run on client side.Tchad
P
0

also i think it is good idea if you want you can add a middle-ware where you can add anything you want to the theme layer including user,config and moment:

// config, user, moment to the theme layer
app.use(function (req, res, next) {
    // grab reference of render
    var _render = res.render;
    // override logic
    res.render = function (view, options, fn) {
        // extend config and continue with original render
        options = options || {};
        options.config = config;
        options.moment = moment;
        if (req.user && req.user.toJSON) {
            options.user = req.user.toJSON();
        }
        _render.call(this, view, options, fn);
    }
    next();
});
Praetor answered 8/3, 2016 at 12:25 Comment(0)
D
0

I wrote a helpers to return moment for using on ejs view and layouts.

./helpers/utils/get-moment.js

const moment = require('moment');

module.exports = {
    friendlyName: 'formatMoney',
    description: 'format money number.',
    inputs: {},
    sync: true,
    exits: {},
    fn: function (inputs, exits) {
        return exits.success(moment);
    }
};

Then using:

const moment = sails.helpers.utils.getMoment();
Diptych answered 5/6, 2018 at 7:27 Comment(1)
Please explain your lines of code so other users can understand its functionality. Thanks!Jointless
B
0

As of Node v12.8.3, it seems that you can pass require directly to EJS templates, i.e. this works:

const ejs = require('ejs')
let renderedHTML = ejs.render(`<% const moment = require('moment') %>`, { require })
Barris answered 26/8, 2020 at 13:0 Comment(1)
can you add a little more info? How do I use it in ejsHaleyhalf
P
0

can use moment.js modules by embedding moment.js_cdn's_scripts in your .ejs file like this way: enter image description here

Plight answered 12/1, 2024 at 15:18 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.