Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the proper way to check for existence of variable in an EJS template (using ExpressJS)?

On the EJS github page, there is one and only one simple example: https://github.com/visionmedia/ejs

Example

<% if (user) { %>
    <h2><%= user.name %></h2>
<% } %>

This seems to be checking for the existence of a variable named user, and if it exists, do some stuff. Duh, right?

My question is, why in the world would Node throw a ReferenceError if the user variable doesn't exist? This renders the above example useless. What's the appropriate way to check for the existence of a variable? Am I expected to use a try/catch mechanism and grab that ReferenceError?

ReferenceError: user is not defined
    at IncomingMessage.anonymous (eval at <anonymous> (/usr/local/lib/node/.npm/ejs/0.3.1/package/lib/ejs.js:140:12))
    at IncomingMessage.<anonymous> (/usr/local/lib/node/.npm/ejs/0.3.1/package/lib/ejs.js:142:15)
    at Object.render (/usr/local/lib/node/.npm/ejs/0.3.1/package/lib/ejs.js:177:13)
    at ServerResponse.render (/usr/local/lib/node/.npm/express/1.0.7/package/lib/express/view.js:334:22)
    at Object.<anonymous> (/Users/me/Dropbox/Projects/myproject/server.js:188:9)
    at param (/usr/local/lib/node/.npm/connect/0.5.10/package/lib/connect/middleware/router.js:146:21)
    at pass (/usr/local/lib/node/.npm/connect/0.5.10/package/lib/connect/middleware/router.js:162:10)
    at /usr/local/lib/node/.npm/connect/0.5.10/package/lib/connect/middleware/router.js:152:27
    at Object.restrict (/Users/me/Dropbox/Projects/myproject/server.js:94:5)
    at param (/usr/local/lib/node/.npm/connect/0.5.10/package/lib/connect/middleware/router.js:146:21)

I understand that I could make this error go away by simply adding a "user" local variable in my server code, but the whole point here is that I want to check for the existence of such variables at runtime using your every day if/else nullcheck type pattern. An exception for a variable that doesn't exist seems ridiculous to me.

like image 365
Aashay Desai Avatar asked Mar 21 '11 00:03

Aashay Desai


People also ask

How do you use variables in EJS?

It is possible to access JS variable in . ejs file. You just need to pass the JS object as second parameter of res. render() method.

What is EJS templating?

EJS (Embedded JavaScript Templating) is one of the most popular template engines for JavaScript. As the name suggests, it lets us embed JavaScript code in a template language that is then used to generate HTML.

What is view engine in EJS?

View engines allow us to render web pages using template files. These templates are filled with actual data and served to the client. There are multiple view engines, the most popular of which is Embedded Javascript (EJS).


10 Answers

The same way you would do it with anything in js, typeof foo == 'undefined', or since "locals" is the name of the object containing them, you can do if (locals.foo). It's just raw js :p

like image 63
tjholowaychuk Avatar answered Oct 29 '22 15:10

tjholowaychuk


Try prepending the variable with locals

Example: if(locals.user){}

like image 30
spencer.sm Avatar answered Oct 29 '22 15:10

spencer.sm


<% if (locals.user) { %>

 // Your logic goes here 

<% } %>
like image 28
Anirudh Avatar answered Oct 29 '22 16:10

Anirudh


You can create a view helper which checks for "obj === void 0", this one is for express.js:

res.locals.get = function() {
    var args = Array.prototype.slice.call(arguments, 0);
    var path = args[0].split('.');
    var root = this;
    for (var i = 0; i < path.length; i++) {
        if(root[path[i]] === void 0) {
            return args[1]?args[1]:null;
        } else {
            root = root[path[i]];
        }
    };
    return root;
}

Then use it in the view like

<%- get('deep.nested.non.existent.value') %>  //returns: null
<%- get('deep.nested.non.existent.value', "default value") %> //returns: default value
like image 36
Paulius Uza Avatar answered Oct 29 '22 16:10

Paulius Uza


To check if user is defined, you need to do that:

<% if (this.user) { %>
   here, user is defined
<% } %>
like image 39
HenioJR Avatar answered Oct 29 '22 15:10

HenioJR


I've come across the same issue using node.js with mongoose/express/ejs when making a relation between 2 collections together with mongoose's populate(), in this case admins.user_id existed but was related to an inexistant users._id.
So, couldn't find why:

if ( typeof users.user_id.name == 'undefined' ) ...

was failing with "Cannot read property 'name' of null" Then I noticed that I needed to do the checking like this:

if ( typeof users.user_id == 'undefined' ) ...

I needed to check the "container" of 'name', so it worked!
After that, this worked the same:

if ( !users.user_id ) ...  

Hope it helps.

like image 26
aesede Avatar answered Oct 29 '22 15:10

aesede


Came to this page for an answer but I came up with a shorter inline syntax for it which is:

 <h2><%= user.name ? property.escrow.emailAddress : '' %></h2>
like image 21
Adam Boostani Avatar answered Oct 29 '22 16:10

Adam Boostani


This may help somebody.

<p><%= locals?.message %></p>

or

<p><%= locals.message || '' %></p>
like image 23
viniciusalvess Avatar answered Oct 29 '22 16:10

viniciusalvess


What I do is just pass a default object I call 'data' = '' and pass it to all my ejs templates. If you need to pass real data to ejs template, add them as property of the 'data' object.

This way, 'data' object is always defined and you never get undefined error message, even if property of 'data' exist in your ejs template but not in your node express route.

like image 40
Robert Brax Avatar answered Oct 29 '22 15:10

Robert Brax


For your if statement you need to use typeof:

<% if (typeof user == 'object' && user) { %>

<% } %>
like image 25
Fabien Thetis Avatar answered Oct 29 '22 15:10

Fabien Thetis