trying to format a date on jade template
Asked Answered
T

5

18

I have an index.js:

exports.index = function(req, res){
  db.courses.find(function(err, currentCourses) {
    res.render('index', {
      currentCourses: currentCourses
    });
  });
};

And on my jade template:

tr
    td #{currentCourses[0].start}

Which is a date, formatted as "Sun Sep 29 2013 00:00:00 GMT+0100 (BST)".

How can I format it to "29 Sep 2013"?

Edit (after Ed Hinchliffe's comments):

-function prettyDate(dateString){
    -var d = date.getDate(dateString);
    -var monthNames = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ];
    -var m = monthNames[date.getMonth()];
    -var y = date.getFullYear();
    -return d+' '+m+' '+y;
-} 
for course in currentCourses
    tr
        td #{prettyDate(course.start)}
Thermionics answered 4/6, 2013 at 16:10 Comment(0)
U
12

Not particularly easy unfortunately. You'll need a function to format a string either inside your template, or outside (and pass the pretty string).

Something like this (JADE)

-function prettyDate(dateString){
    //if it's already a date object and not a string you don't need this line:
    -var date = new Date(dateString);
    -var d = date.getDate();
    -var monthNames = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ];
    -var m = monthNames[date.getMonth()];
    -var y = date.getFullYear();
    -return d+' '+m+' '+y;
-}


tr
   td #{prettyDate(currentCourses[0].start)}
Underscore answered 4/6, 2013 at 16:17 Comment(4)
Ah ok. If you have the function outside the template, how would you pass it in?Thermionics
have exactly the same function (Without the - escape characters), and call it on the string first. Given (I assume) you have a lot of these in an array of objects, it might be better just to keep it in the template as above rather than iterate over the whole object first converting them all.Underscore
Thanks for that. I've added that code (see my edit), and I now get the following error: > 57| -var d = date.getDate(); object has no getDate method. Any ideas?Thermionics
Don't worry, I corrected my code and it now works. Thanks very much!Thermionics
B
62

My solution is:

Add momentjs to your express application locals like this:
app.locals.moment = require('moment');

Then you can use moment in any jade files:
span='(Created at: ' + moment(obj.createTime).format("YYYY/MM/DD") + ')'

Reference:
Making use of utility libraries in server-side Jade templates

Bambi answered 20/9, 2014 at 16:33 Comment(2)
td= moment(obj.timestampSent).format('DD.MM.YYY')Puiia
Good answer, easy. Any benefit to this approach as opposed to a traditional script(src='moment.min.js')?Alphabetical
U
12

Not particularly easy unfortunately. You'll need a function to format a string either inside your template, or outside (and pass the pretty string).

Something like this (JADE)

-function prettyDate(dateString){
    //if it's already a date object and not a string you don't need this line:
    -var date = new Date(dateString);
    -var d = date.getDate();
    -var monthNames = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ];
    -var m = monthNames[date.getMonth()];
    -var y = date.getFullYear();
    -return d+' '+m+' '+y;
-}


tr
   td #{prettyDate(currentCourses[0].start)}
Underscore answered 4/6, 2013 at 16:17 Comment(4)
Ah ok. If you have the function outside the template, how would you pass it in?Thermionics
have exactly the same function (Without the - escape characters), and call it on the string first. Given (I assume) you have a lot of these in an array of objects, it might be better just to keep it in the template as above rather than iterate over the whole object first converting them all.Underscore
Thanks for that. I've added that code (see my edit), and I now get the following error: > 57| -var d = date.getDate(); object has no getDate method. Any ideas?Thermionics
Don't worry, I corrected my code and it now works. Thanks very much!Thermionics
C
7

The above solution from Zhifeng Hu gave me the right direction. Unfortunately app.locals.moment did not worked for me.

But you can pass the require('moment') also directly into the object for the template attributes.

var data = {
  title: 'some nice title',
  updateDate: new Date(),
  ....,
  moment: require( 'moment' )
};

And then pass the data object as usual to the template function.

var template = pug.compile( source );
var html = template( data );

Source File example:

doctype html
html
  head
    title= title
  body
    div= moment(updateDate).format('YYYY-MM-DD')
Choice answered 1/3, 2017 at 15:16 Comment(0)
E
2

I like to take an approach similar to @Zhifeng Hu, but instead of requiring everything into locals, I just require "require", then I can pull things in as needed in my templates.

app.use((req, res, next) => { res.locals.require = require; next() })

and then in Jade/Pug

- const moment = require('moment')
div Created at: #{moment(data.createdAt).fromNow()}

Basically the same thing, but I can keep the require code in the template where it's used.

Edette answered 19/11, 2018 at 20:24 Comment(0)
C
-3

You should format the date server-side. Limit the amount of logic done inside the template to bare minimum - ideally nothing at all.

Congresswoman answered 16/7, 2014 at 15:16 Comment(1)
I would argue with this. Something like date formatting is exactly the type of presenting you should do in a template, not in a controller, etc.Laden

© 2022 - 2024 — McMap. All rights reserved.