LearningAsIGo
LearningAsIGo

Reputation: 1311

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.

Upvotes: 33

Views: 70876

Answers (8)

jt3k
jt3k

Reputation: 700

I have two solutions that may not suit everyone.

1. The "grab and run" method

At the top of main.ejs write the following construct

<% const helpers = {}; include('./helpers', { helpers }); %>

Inside helpers.ejs write the following:

<%

Object.assign(helpers, {
  lower(arg) { return String(arg).toLowerCase() },
  upper(arg) { return String(arg).toUpperCase() },
  // some other helpers here

})

%>

Now in main.ejs we can use these functions

<h1><%= helpers.upper('your text here') %></h1>

2. World mutation method

This is similar to the previous method, but instead of mutating the local helpers variable, a "variable_object" from the parent context is passed inside the helpers.ejs file, which is supplemented with the necessary variables.

This is what it looks like:

At the top of main.ejs write the following:

<% include('./helpers', { locals }); %>

In helpers.ejs

Object.assign(locals, {
  lower(arg) { return String(arg).toLowerCase() },
  upper(arg) { return String(arg).toUpperCase() },
  // some other helpers here
});

now in main.ejs

<%= upper('lololo') %>

Good luck!

Upvotes: 0

Faaiq
Faaiq

Reputation: 391

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

Upvotes: 39

Rick
Rick

Reputation: 13500

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

Upvotes: 2

Rik
Rik

Reputation: 1987

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}

Upvotes: 8

Sod
Sod

Reputation: 1

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.

Upvotes: -1

Adam Murphy
Adam Murphy

Reputation: 31

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" >

Upvotes: 3

Siddhartha Chowdhury
Siddhartha Chowdhury

Reputation: 2732

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

Upvotes: 13

LearningAsIGo
LearningAsIGo

Reputation: 1311

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.

Upvotes: 56

Related Questions