Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Struggle with EJS and scope of -not so- "local" variables

I'm wondering how I should write my node.js application, using EJS template. I'm actually looking for a proper way to define local variables with default values in a partial/template.

I'll exlain quickly of it works now:

When I call a template, like this:

<%- partial(__view.partialPath('tagPopover'), {
    title_popover: sentence.nickname,
    content_tag: '#' + sentence.nickname,
    icon_popover: 'http://placehold.it/64x64'
}) %>

I manage the default values this way, in the _tagPopover.ejs partial:

title_popover = typeof title_popover != 'undefined' ? title_popover : ''
classes_tag = typeof classes_tag != 'undefined' ? classes_tag : 'tags'
icon_popover = typeof icon_popover != 'undefined' ? icon_popover : false
content_tag = typeof content_tag != 'undefined' ? content_tag : ''

I don't use the var keyword, because it doesn't work at all, for instance, if I do:

var title_popover = typeof title_popover != 'undefined' ? title_popover : ''

Then EJS will interprate the var title_popover and create a local variable before to read the actual value of the variable title_popover. So I'll end up with a null, even if I actually sent a parameter...

When I discovered that, I decided to not use the var keyword... But I just recently discovered that all the variables that I create this way are actually global! Meaning that it's a really bad solution because I may likely end up rewriting global variables by loading a view!

I believe this will be a struggle later and I don't want my views to set/reset global variables by default (who would?!)

Do you have any solution for this? I thought about several already but I don't like any:

  1. Use the var keyword but also use a before pattern for local variable to avoid resetting parameters: var l_title_popover = typeof title_popover != 'undefined' ? title_popover : ''. This looks bad and confusing as hell.
  2. Use a namespace like view.title_popover = typeof title_popover != 'undefined' ? title_popover : ''. I want my variables to be locals, not globals, if I do so I will have something global that will exist in memory all the time.

How would you deal with that? I'm quite curious, maybe there is some EJS way to handle that or a helper, I don't know.

like image 673
Vadorequest Avatar asked Oct 31 '22 07:10

Vadorequest


1 Answers

There's a concept of filters in ejs. Also see adding-filters.

Basically I think you're looking for something similar to this.. Code below will set title_popover if exists in the res.locals, otherwise it sets to 'some default value'

<%=: locals | get:'title_popover','some default value' %>  

ejs.filters.get = function(obj, prop, default) {
  return obj[prop] === undefined ? default : obj[prop];
};  

I believe this is the easiest way to do it in ejs, but there might be some other methods. Looks like this actually being discussed on a github ticket :)

EDIT - This blog post seems to give some alternatives using the underscore library. Looks like they're wrapping the template in a layout somehow (I haven't fully grokked the article but it seems to make sense on the surface).

I've only used the above way however.

like image 73
Justin Maat Avatar answered Nov 09 '22 16:11

Justin Maat