To judge whether a variable in the ejs - node.js

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)

Related

Where should I define JS function to call in EJS template

I am working on a template where I am trying to render template using express and ejs. As to the standard structure of node app, I have app.js file which which contains functions like following:
app.locals.getFlag = function(country) {
var flag_img_name = "";
if (country.toLowerCase() == "us") {
flag_img_name = "flag_us16x13.gif";
}
else if (country.toLowerCase() == "ca"){
flag_img_name = "flag_ca16x13.gif";
}
return flag_img_name;
}
I have some_template.ejs file which calls this function like follows:
<img src="http://some_url_path/<%=getFlag(data_point[0].country_name) %>" width="16" height="14" alt="country" >
and it works just fine. However, I have around 15-20 functions like this and I don't want to define all of them in app.js. Is there any other place where I can define these functions and call them in the template same way as I am doing now? If yes, what would be the way to define them so that they are accessible like they are right now.
I am new to node, express and ejs and not sure of different techniques. If someone could shed a light over it, it would be great. Thank you in advance.
Just posting this answer here for someone who would might end up on this question while resolving same issue.
All you have to do is create new file (say functions.ejs) and include it in the .ejs file where you want to call that function. So, I have function like this in file named functions.ejs:
<%
getPriceChgArrow = function(value) {
arrow_img_name = "";
if (value < 0) {
arrow_img_name = "arrow_down12x13.gif";
}
else {
arrow_img_name = "arrow_up12x13.gif";
}
return arrow_img_name;
}
%>
Then include functions.ejs into the file you want to call function from. Say, I want to call this function in quote.ejs file. So, I would include it as follows:
<% include *file_path*/functions %>
Just use this function at appropriate location in your ejs file from where you want to call it. For example:
<img src = "http:/some_url/<% getPriceChgArrow(data_point[0].value) %>" />
and you are all set. Hope this helps someone.
Create common functions in js file helper.js.
function common1() {
//function body
}
function common2(key) {
//function body
}
module.exports = {
common1: common1,
common2: common2
}
And then require this file in your node function
var helper = require('./helper');
and then pass this helper with ejs render
res.render('index', { helper:helper });
And use your function is ejs file
<%= helper.common1() %>
That's It
Well, for some reason the accepted answer didn't worked out for me. Also it doesn't makes sense to create a separate *.ejs file for each of my functions and then importing the file in view - specially when I have very simple logic to be implemented.
In fact it is very simple and easy to define function and use it in the view
I did this:
<%
// ------ Define a function
get_tree = function(tree){
for(var i in tree){
%>
<%= tree[i].title %>
<%
}
}
// ----- Call the above declared function
get_tree(tree);
%>
And it works!
Thanks
You can just require a separate file and set app.locals to this
app.locals = require('./path/helpers')
In helpers.js:
getFlag = function(country) {
var flag_img_name = "";
if (country.toLowerCase() == "us") {
flag_img_name = "flag_us16x13.gif";
}
else if (country.toLowerCase() == "ca"){
flag_img_name = "flag_ca16x13.gif";
}
return flag_img_name;
}
anotherFunction=function(x){
return 'hello '+x
}
module.exports={getFlag, anotherFunction}
It seems the easiest way to do this is to pass the function in attached to the object with all the data for the render:
in your js:
const data = {
...all other data,
getFlags: function(country) {
var flag_img_name = "";
if (country.toLowerCase() == "us") {
flag_img_name = "flag_us16x13.gif";
} else if (country.toLowerCase() == "ca"){
flag_img_name = "flag_ca16x13.gif";
}
return flag_img_name;
}
};
ejs.render(template, data);
in your template:
<img src="http://some_url_path/<%=getFlag(data_point[0].country_name) %>" width="16" height="14" alt="country" >
The order you setup your file has an importance on how the functions are defined. The execution is top to bottom not on document evaluation. Example below to setup your functions.
document.html
<section class="container">
<%- include('./helpers/common') %>
<%- include('./home') %>
</section>
common.ejs
<%
MyFunction = function() {
// Write your code here
}
%>
home.ejs
<% if(MyFunction() ) { %>
<!-- Write your HTML markup -->
<% }%>
In a js file, create a instance of the function like: if your function name is test (), Var ren = test (); will create a reference to this function.
Before rendering data to the ejs page add the reference variable ren to that object:
Data.ren = ren();
Res.render(Data)
And now in ejs while when you call <% ren() %> it will call the fonction.

Unable to display flash message in view with ejs template

I am a newbie in NodeJS. I have a problem that I am unable to show flash message in my view.
Here is my Controller,
index : function(req, res){
res.locals.flash = _.clone(req.session.flash);
res.locals.layout = false;
res.view('login');
},
login : function(req, res){
....
if(!admin){
req.session.flash = {
err : 'User is not found.' // My flash message
}
res.locals.layout = false;
res.redirect('login');
return;
}
.....
}
Here is my view,
<% if(flash && flash.err) { %>
<div class="alert alert-danger">
<% JSON.stringify(flash.err) %>
</div>
<% } %>
When login is false, it show only an empty alert box.
And I have a second problem. When I refresh page, The alert box isn't disappeared.
Could someone help me please.
Thanks a lot.
The alert box keeps on appearing because the req.session.flash object persists the session, so you need to null that out once it's used, or you can just simply use req.flash(), which does that for you. So change your index method to something like this:
index: function(req, res) {
// req.flash() returns the contents of req.session.flash and flushes it
// so it doesn't appear on next page load. No need to clone.
res.locals.flash = req.flash();
res.locals.layout = false;
res.view('login');
},
Now, onto the second problem. The error messages aren't appearing because you aren't using the proper EJS syntax to output escaped values into the view. All you need to do is change your code to this:
<% if(flash && flash.err) { %>
<div class="alert alert-danger">
// Change <% to <%=
<%= flash.err %>
</div>
<% } %>
No need to JSON.stringify, unless you like the quotes. Notice that I changed the <% to <%=, which in EJS means "escape this and output it". It's not template HTML or anything like that, so it's okay to escape it anyway.

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?

Express, EJS, challenge with testing for undefined

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
<% } %>

Resources