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

node.jsExpressEjs

node.js Problem Overview


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.

node.js Solutions


Solution 1 - node.js

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

Solution 2 - node.js

Try prepending the variable with locals

Example: if(locals.user){}

Solution 3 - node.js

<% if (locals.user) { %>

 // Your logic goes here 

<% } %>

Solution 4 - node.js

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

Solution 5 - node.js

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

<% if (this.user) { %>
   here, user is defined
<% } %>

Solution 6 - node.js

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.

Solution 7 - node.js

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>

Solution 8 - node.js

This may help somebody.

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

or

<p><%= locals.message || '' %></p>

Solution 9 - node.js

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.

Solution 10 - node.js

For your if statement you need to use typeof:

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

<% } %>

Solution 11 - node.js

I had same issue, and luckily, I found that there is also a short-circuit function in JS (I knew there was one in Ruby and some other languages).

On my server/controller side (this is from Node.js/Express):

return res.render('result', {survey_result : req.session.survey_result&&req.session.survey_result.survey }); 

See what I did there? The && which follows after a possibly undefined variable (i.e. request.session.survey_result object, which might or might not have form data) is the short-circuit notation in JS. What it does is only evaluate the part that follows the && if the part to the left of the && is NOT undefined. It also does not throw an error when the left part IS undefined. It just ignores it.

Now, in my template (remember that I passed the object req.session.survey_result_survey object to my view as survey_result ) and then I rendered fields as:

<table>
    <tr>
        <td> Name:</td>
        <td> <%=survey_result&&survey_result.name%></td>
    </tr>
    <tr>
        <td> Dojo Location:</td>
        <td> <%=survey_result&&survey_result.dojo_loc%></td>
    </tr>
    <tr>
        <td> Favourite Language:</td>
        <td> <%=survey_result&&survey_result.fave_lang%></td>
    </tr>

I used short-circuit there also, just for safe-keeps.

When I tried it with previously suggested ways, just:

<% if (typeof survey_result !== undefined) { %>
... <!-- some js and/or html code here -->
<% } %>

Sometimes, it would still try to evaluate the properties within the IF statement...Maybe someone can offer an explanation as to why?

Also, I wanted to correct that undefined needs to be without the single quotes, as I saw done in previous examples. Because the condition will never evaluate to true, as you are comparing a String value 'undefined' with a datatype undefined.

Solution 12 - node.js

You can use this trick :

user.name // stops code execution,if user is undefined
(scope.user||0).name // === undefined

where scope is parent object of user

Solution 13 - node.js

if you plan to use the same object often, you could use a function like this:

<% function userObj(obj){
    //replace user with what you name your object
    if(typeof user === 'object'){
        let result = user;
        if(obj){
            obj = obj.split('.');
            for(let i = 0; i < obj.length; i++){
                if(obj[i] && obj[i].trim() !== '' && result[obj[i]]){
                    result = result[obj[i]];
                }else{
                    result = false;
                    break;
                }
            }
        }
        return result;
    }
    return false;
} %>

usage:

<% if(userObj('name')){
    <h2><%= userObj('name') %></h2>
} %>

Solution 14 - node.js

I have come up with another solution.

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

I hope this helps.

Solution 15 - node.js

The safest and only solution that worked for me

<% if (typeof user !== 'undefined' && typeof user.name !== 'undefined') { %>
    <h2><%= user.name %></h2>
<% } %>

Or a short version

<% (typeof user !== 'undefined' && typeof user.name !== 'undefined') ? user.name : '' %>

Solution 16 - node.js

I found what I believe to be a better solution on Joe Andrieu's blog:

<%= user.name ? user.name : '' %>

This applies in more situations than the other answers (i.e., when you need to check if a single property exists).

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAashay DesaiView Question on Stackoverflow
Solution 1 - node.jstjholowaychukView Answer on Stackoverflow
Solution 2 - node.jsspencer.smView Answer on Stackoverflow
Solution 3 - node.jsAnirudhView Answer on Stackoverflow
Solution 4 - node.jsPaulius UzaView Answer on Stackoverflow
Solution 5 - node.jsHenioJRView Answer on Stackoverflow
Solution 6 - node.jsaesedeView Answer on Stackoverflow
Solution 7 - node.jsAdam BoostaniView Answer on Stackoverflow
Solution 8 - node.jsviniciusalvessView Answer on Stackoverflow
Solution 9 - node.jsRobert BraxView Answer on Stackoverflow
Solution 10 - node.jsFabien ThetisView Answer on Stackoverflow
Solution 11 - node.jsYekatjarina Aljaksandrayna ShuView Answer on Stackoverflow
Solution 12 - node.jsAlex SzücsView Answer on Stackoverflow
Solution 13 - node.jsSwiftNinjaProView Answer on Stackoverflow
Solution 14 - node.jsomarView Answer on Stackoverflow
Solution 15 - node.jsFouadView Answer on Stackoverflow
Solution 16 - node.jsBrettView Answer on Stackoverflow