Express, EJS, challenge with testing for undefined - node.js

I'm creating a simple website with nodejs using the express framework, couchdb for a database and EJS for templating. There will be times when some of my fields are null or undefined in some of my JSON docs, and I need to handle that.
<% if (typeof test !== 'undefined') { %>
<p><%= test %></p>
<% } %>
That bit of code seems to handle the 'test' field being undefined just fine, but the code below throws an error that says 'test is undefined'
<% if (test) { %>
<p><%= test %></p>
<% } %>
Why doesn't javascript understand test to be undefined and then just put false in the if clause?

Because the concept of "undefined" is different than the state of a variable being defined in the JavaScript language. The reasons for this are understandable but the effects can be confusing, especially regarding variable names vs object properties.
You have demonstrated how trying to access an undefined variable will throw an exception. Don't confuse this state (a variable is not defined) with the "undefined" type:
if (bogusVariable) { // throws ReferenceError: bogusVariable is not defined.
typeof(bogusVariable); // => undefined - wow, that's confusing.
However, properties of objects which are not defined can be tested safely:
var x = {}; // an object
x.foo; // => undefined - since "x" has no property "foo".
typeof(x.foo); // => undefined
if (!x.foo) { /* true */ }
You could take advantage of this property by noting that all variables are actually properties of the "global" object (either "global" or "window", in web browsers).
bogus; // => ReferenceError: bogus is not defined.
global.bogus; // => undefined (on node/rhino)
window.bogus; // => undefined (on web browsers)
So you might be able to write your EJS code as such:
<% if (global.test) { %>
<p><%= test %></p>
<% } %>
Yes, it's confusing, as are many parts of the JavaScript language.

most languages are like this:
irb
>> foo
NameError: undefined local variable or method `foo' for main:Object
from (irb):1

To check if test is defined, you need to do that:
<% if (this.test) { %>
here, test is defined
<% } %>

Related

Why does a semicolon in ejs template throws error

In the following code if the semicolon is removed the template engine does not throw error, else the error is thrown.
<ul>
<% for (i = 0; i < array.length; ++i) { %>
<%= JSON.stringify(array[i]); %>
<% } %>
</ul>
Although putting semicolon syntactically correct, why does the template engine throw error ?
As #torazaburo said, the contents between <=% and %> are an expression that gets parsed by ejs. However, think of it this way:
Your goal is to render the contents returned from JSON.stringify to the page right? So in that case, think of ejs expressions as implicitly calling .toString() on the result of the expression and then inserting that string into the page. By adding a semi-colon you've terminated the statement without assigning the returned value to anything.

Underscore Js _.each used with ejs error

I am trying to display the value in array using _.each and EJS dynamically. I am getting the values when i do it manually,but getting Unexpected token ; error while using _.each loop.
Here is the code
`<% _.each(pro,function(prof) { %>
alert(prof.Name);
<% } %>`
pro = {[object Object],[object Object]}
when i do it manually,i get the output.
i.e.
`<%= pro[0].Name %>`
Need help! Any other suggestions? Thanks
You seem have missed a parentheses here:
<% }) %>`
Beyond that, I'm not sure you can use underscore inside your EJS templates.
Try using a regular for.
<% for(var i=0; i<prof.length; i++) {%>
<li><%= prof[i] %></li>
<% } %>

To judge whether a variable in the ejs

Here's my application:
index.js
function index(req, res) {
res.render('admin/index');
}
module.exports = index;
index.ejs
<%
if(data) {
%>
<div class="alert alert-danger" role="alert">login fail</div>
<%
}
%>
I got an error saying:
data is not defined
I want to check whether the variable exists, and to display the dialog if it does. What should I do?
Either rewrite the check as follows:
<% if (typeof data !== 'undefined') { %>
... or check the property on locals (local variables object) instead:
<% if (locals.data) { %>
Explanation: when EJS compiles a template into a function, it does not populate its variables' stack based on the options supplied. Instead, it wraps this function with with statement:
with (locals || {}) {
(function() {
// ... here goes the template content
})();
}
Now, the data object (second parameter of render) is passed into the template function as locals variable, it's against this object all the checks are made. The point is, if accessed somevar is never defined in the local template scope (by var statement), and doesn't exist in locals object either, it'll cause a ReferenceError: somevar is not defined error.
(one can disable with-wrapping, setting _with option of template to false, but by default it's just undefined)

ExpressJS + EJS: Avoid "variable is not defined" globally

How to globally avoid EJS throw error when context variable is not defined ? I mean a way to set (in middleware?) for example space or null value for all variables not defined. Now i always use on template something like below. Is better way ?
<% if(typeof locals.variable != 'undefined') { %>
...
<% } %>
I usually just have a middleware that sets some default values for a particular set of routes via res.locals.variable = undefined; or similar. Then you can successfully check if (variable === undefined) in the template for those routes.

express + ejs login widget

I am trying to make easy widget for buttons login/logout.
laout.ejs
<% include ../shared/login_logout %>
login_logout.ejs
<% if ( !common.IsDefined(membershipHelper.GetCurrentUser(request , response)) ) { %>
<li class="pull-right">Login</li>
<% } else { %>
<li class="pull-right">Log Out</li>
<% } %>
membershipHelper.GetCurrentUser - this method checks request session for user_id and if it finds it returns user if it is found in db(mongoDB) else it returns null. As user is returned in callback function of User.findById ejs file receives "undefined" always. I thought to put this GetCurrentUser in the middleware but it look like I can't set null or undefined to locals variable
What can be solution for this problem?

Resources