Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create global variables accessible in all views using Express / Node.JS?

Ok, so I have built a blog using Jekyll and you can define variables in a file _config.yml which are accessible in all of the templates/layouts. I am currently using Node.JS / Express with EJS templates and ejs-locals (for partials/layouts. I am looking to do something similar to the global variables like site.title that are found in _config.yml if anyone is familiar with Jekyll. I have variables like the site's title, (rather than page title), author/company name, which stay the same on all of my pages.

Here is an example of what I am currently doing.:

exports.index = function(req, res){     res.render('index', {          siteTitle: 'My Website Title',         pageTitle: 'The Root Splash Page',         author: 'Cory Gross',         description: 'My app description',         indexSpecificData: someData     }); };  exports.home = function (req, res) {     res.render('home', {         siteTitle: 'My Website Title',         pageTitle: 'The Home Page',         author: 'Cory Gross',         description: 'My app description',         homeSpecificData: someOtherData     }); }; 

I would like to be able to define variables like my site's title, description, author, etc in one place and have them accessible in my layouts/templates through EJS without having to pass them as options to each call to res.render. Is there a way to do this and still allow me to pass in other variables specific to each page?

like image 339
Cory Gross Avatar asked May 08 '13 23:05

Cory Gross


People also ask

How do I create a global variable in Express?

To make a global variable, just declare it without the var keyword. (Generally speaking this isn't best practice, but in some cases it can be useful - just be careful as it will make the variable available everywhere.) //we can now access 'app' without redeclaring it or passing it in... /* * GET home page. */ app.

Can global variables be accessed anywhere?

Variables that are created outside of a function are known as Global Variables . A global variable is one that can be accessed anywhere . This means, global variable can be accessed inside or outside of the function.

How do I assign a global variable in node JS?

To set up a global variable, we need to create it on the global object. The global object is what gives us the scope of the entire project, rather than just the file (module) the variable was created in. In the code block below, we create a global variable called globalString and we give it a value.

What is var Express require (' Express ')?

var express = require('express'); => Requires the Express module just as you require other modules and and puts it in a variable. var app = express(); => Calls the express function "express()" and puts new Express application inside the app variable (to start a new Express application).


2 Answers

After having a chance to study the Express 3 API Reference a bit more I discovered what I was looking for. Specifically the entries for app.locals and then a bit farther down res.locals held the answers I needed.

I discovered for myself that the function app.locals takes an object and stores all of its properties as global variables scoped to the application. These globals are passed as local variables to each view. The function res.locals, however, is scoped to the request and thus, response local variables are accessible only to the view(s) rendered during that particular request/response.

So for my case in my app.js what I did was add:

app.locals({     site: {         title: 'ExpressBootstrapEJS',         description: 'A boilerplate for a simple web application with a Node.JS and Express backend, with an EJS template with using Twitter Bootstrap.'     },     author: {         name: 'Cory Gross',         contact: '[email protected]'     } }); 

Then all of these variables are accessible in my views as site.title, site.description, author.name, author.contact.

I could also define local variables for each response to a request with res.locals, or simply pass variables like the page's title in as the optionsparameter in the render call.

EDIT: This method will not allow you to use these locals in your middleware. I actually did run into this as Pickels suggests in the comment below. In this case you will need to create a middleware function as such in his alternative (and appreciated) answer. Your middleware function will need to add them to res.locals for each response and then call next. This middleware function will need to be placed above any other middleware which needs to use these locals.

EDIT: Another difference between declaring locals via app.locals and res.locals is that with app.locals the variables are set a single time and persist throughout the life of the application. When you set locals with res.locals in your middleware, these are set everytime you get a request. You should basically prefer setting globals via app.locals unless the value depends on the request req variable passed into the middleware. If the value doesn't change then it will be more efficient for it to be set just once in app.locals.

like image 189
Cory Gross Avatar answered Sep 27 '22 22:09

Cory Gross


You can do this by adding them to the locals object in a general middleware.

app.use(function (req, res, next) {    res.locals = {      siteTitle: "My Website's Title",      pageTitle: "The Home Page",      author: "Cory Gross",      description: "My app's description",    };    next(); }); 

Locals is also a function which will extend the locals object rather than overwriting it. So the following works as well

res.locals({   siteTitle: "My Website's Title",   pageTitle: "The Home Page",   author: "Cory Gross",   description: "My app's description", }); 

Full example

var app = express();  var middleware = {      render: function (view) {         return function (req, res, next) {             res.render(view);         }     },      globalLocals: function (req, res, next) {         res.locals({              siteTitle: "My Website's Title",             pageTitle: "The Root Splash Page",             author: "Cory Gross",             description: "My app's description",         });         next();     },      index: function (req, res, next) {         res.locals({             indexSpecificData: someData         });         next();     }  };   app.use(middleware.globalLocals); app.get('/', middleware.index, middleware.render('home')); app.get('/products', middleware.products, middleware.render('products')); 

I also added a generic render middleware. This way you don't have to add res.render to each route which means you have better code reuse. Once you go down the reusable middleware route you'll notice you will have lots of building blocks which will speed up development tremendously.

like image 30
Pickels Avatar answered Sep 27 '22 22:09

Pickels