how to get locals in Express from routes - javascript

I have a variable defined as local on my app.js file like this (app is really express) :
app.locals.weather = { /* unimportant content here */ };
Now, I want to access that information from my index.js route to print on a ejs template. I'm trying this, but it says it is undefined:
var express = require('express');
var router = express.Router();
console.log(express.locals);
What is the right way to do that?

The documentation states:
You can access local variables in templates rendered within the application.
In other words, you don't have to do anything special to pass weather to your EJS template, by assigning it to app.locals you make it available through your app.

All keys created under app.locals are available directly to the template.
In your template you should not refer to it as locals.weather, instead try only weather
var express = require('express');
var app = express();
app.set('view engine', 'ejs');
app.set('views', __dirname + '/templates');
app.locals.weather = 'hot';
app.get('/', function(req, res){
console.log('received req');
res.render('hello');
});
app.listen(3000)
And the ejs template
<!DOCTYPE html>
<div>
hello ejs
</div>
<div>
<%= weather %>
</div>
And it works

Related

Error: Module "html" does not provide a view engine (Express)

I'm trying to set up a simple routing app but I keep running int the error when rendering a page.
Error: Module "html" does not provide a view engine.
What is odd is I've specified the view engine in my app.js file but I'm still getting the error
// app.js
var express = require('express');
var app = express();
var router = express.Router();
// Need to import the route file
var chef = require('./chef');
app.use('/chef', chef);
// Set directory to contain the templates ('views')
app.set('views', __dirname + '/views');
// Set view engine to use
app.set('view engine', 'html');
app.use(function(err, req, res, next) {
console.error(err.stack);
res.status(500).send('Something broke!');
});
// chef.js
var express = require('express');
var routes = express.Router();
routes.get('/', (req, res) => {
//res.send("I'm here!")
res.render('chef');
});
module.exports = routes;
// views/chef.html
Some HTML file here here ..
In the chef.js file when I just want to test if the route is working I uncomment res.send ... which sends "I'm here" to the DOM.
However whenever I try res.render to render the chef.html page I get the error above. Which I find odd because I've set the view engine in app.js.
Suggestions on how to render my HTML file?
use res.sendFile('/fileName.html'); instead of res.render()
for sending file , we used res.sendFile(fullPath) and if you are using other than HTML language then you should have to use res.render().
res.render() for template like ejs, pug etc.

how to resolve ExpressJS routing when using AngularJS html5Mode (back4app/Parse-Server)

I'm using back4app BaaS service that uses Parse-Server. For the ClientSide I'm running AngularJS with html5Mode(true);
My problem is that this is NOT working: http://app.rizop.tv/dashboard
While this is working right: http://app.rizop.tv
Any idea how to fix expressJS to handle my routes in the right way?
I have this config:
cloud\app.js
// Helper modules that will be used
var path = require('path');
var bodyParser = require('body-parser')
// This imports the Router that uses the template engine
var index = require('./routers/index');
// Sets the template engine as EJS
app.set('view engine', 'ejs');
// This defines that the 'views' folder contains the templates
app.set('views', path.join(__dirname, '/views'));
// These options are necessary to
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
// This bind the Router to the / route
app.use('/', index)
// Starts listening in the routes
app.listen();
cloud\routers\index.js
// Importing express
var express = require('express');
// Creating a Router
var route = express.Router();
// Defining a route that binds the GET method
route.get('/', function(req, res) {
// This is the code that renders the template
res.render('index', {testParam: 'Back4Apper'});
});
module.exports = route;
cloud\views\index.ejs
<!doctype html>
<html>
<head>
<meta charset="utf-8">
...
</body>
...
</body>
</html>
Here is my app structure:
You can make it work by making little changes in app.js and root html file
I assume you already defined $locationProvider.html5Mode(true); where you defined your routes. Then define base href in your index html
<head>
<base href="/">
...
</head>
This answer might be helpful to configure your server
The file at cloud/app.js should not have app.listen() on its final line, due to the fact that you are using Cloud Code. Can you please try that?
I have ran into the same problem and did the following
I've put this route as the last option, so when the express router ran out of options it will render the index file where is the angular app. Angular internal router will resolve that route and draw the view.
router.get('*', function (req, res) {
res.render('index', {testParam: 'Back4Apper'});
});
Obviously you can write a smarter regex instead of * according to your needs but you get the idea.

What's the best way to access the express 'app' object from inside a separate route file?

In Express 4, by default, routes are loaded from a separate file:
app.use('/', routes);
Would load routes/index.js.
I have a third-party library that attaches to app itself. Is there a preferred way to access app from inside routes/index.js?
I've thought about dependency injection ie, routes/index.js does
module.exports = function(app){
(routes go here)
}
and then:
app.use('/', routes(app))
But I wonder if there's a better way. What's the best way to access the express 'app' object from inside a separate route file?
You can simply access app by req.app in your route handlers
I looked at a number of app generators and everyone does it differently.
Mostly though I've seen it work the opposite from what you are asking. The route modules do not get the app passed in, they just return themselves and are attached to the app.
I like to use the following pattern:
routers/hello.js:
var express = require('express');
var router = express.Router();
router.get('/hello', function (req, res) {
res.send('Hello, World!');
});
module.exports = router;
app.js:
var express = require('express');
var app = express();
app.use('/sample', require('./routers/hello'));
// other routers are attached
module.exports = app;
server.js:
var http = require('http');
var app = require('app');
var server = http.createServer(app);
server.listen(3000):
So the modules in routers/ return an Express Router object that are then attached to the app on their respective paths (routes).
This is inspired on the Express Application generator, but uses Routes instead of Routers. My advice, use the linked generator and start from there.

Express, expand variable in static file

I am using express on a nodejs platform and serve my javascript library files using this directive
app.use('/static', express.static(__dirname + '/static'))
Now I want to be able to write something like that, inside one of these static files
[..] var host = <%= host %> [..]
Is there any possibility to expand variables inside statically served files?
Here's an idea you might want to refine:
var ejs = require('ejs');
//Express.js setup
...
app.use('/public/js/myfile.js', function(req, res){
var f = ejs.compile('var host = <%= hostname %>;');
var fileContent = f({hostname: 'somevalue'});
res.setHeader('Content-Type', 'application/javascript');
res.setHeader('Content-Length', fileContent.length);
res.send(fileContent);
});
app.use(express.static(path.join(__dirname, 'public')));
//Routes definition
...
I used ejs since that's what you already use. So the idea is to have a middleware that catches requests to those "dynamic" javascript files, and use the template engine to compile the content.
Note that I use a simple string variable here, but you could read the file from disk and then compile it.
Cheers
You can use loDash's templating with express using lodashinexpress.
Please see my answer here: https://stackoverflow.com/a/19812753/2728686
Using the Jade templating engine you can serve static files and send serverside javascript variables to the static HTML files (or to any jade templates), as such:
Server side (server.js):
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.get('/', ensureAuthenticated, function(request, response){
response.render('index', { data: {currentUser: request.user.id} });
});
app.use(express.static(__dirname + '/www'));
views/index.jade:
!!! 5
script(type='text/javascript')
var local_data =!{JSON.stringify(data)}
include ../www/index.html

How to set path to partials in Node.js with Express, Handlebars and Conslidate

I have a working Node.js site, using Express.js, Handlebars.js and Consolidate.js. I want to use partials for common parts of my templates, but can't work out how to make them work for pages at different URLs.
My /views/ directory contains this:
_footer.html
_header.html
article.html
index.html
The relevant parts of my Node app looks something like:
var express = require('express'),
consolidate = require('consolidate'),
handlebars = require('handlebars'),
path = require('path');
var app = express();
app.engine('html', consolidate.handlebars);
app.set('view engine', 'html');
app.set('views', path.join(__dirname, '/views'));
var partials = {header: '_header', footer: '_footer'};
app.get('/', function(req, res) {
res.render('index', {partials: partials});
};
app.get(/^\/([\w-]+)\/$/, function(req, res) {
res.render('article', {partials: partials});
};
And in my index.html and article.html Handlebars templates I have something like:
{{> header}}
<!-- page content here -->
{{> footer }}
I should be able to access both / (when index.html is rendered) and /foo/ (when article.html is rendered). But it only works for whichever I try to access first after starting the Node server. When I then navigate to the other path, I get errors like:
Error: ENOENT, no such file or directory '/Users/phil/Projects/projectname/views/<!DOCTYPE html>...
with the rest of the _header.html partial following.
I assume I need to somehow set the path to my partials to be absolute somehow, but I can't see how to do that.
For consolidate check that : https://github.com/tj/consolidate.js/issues/18
I would recommend to switch to something a bit more specific like that https://github.com/donpark/hbs it will be simpler.
I had the same exact issue. It seems that consolidate is reusing the "partials" object that you pass, replacing the values with the file content (yuck!).
A workaround is to create a new "partials" object every time. If you don't want to rewrite the whole object every time, you can use a function returning the object literal.
In your case something like the following should work:
var express = require('express'),
consolidate = require('consolidate'),
handlebars = require('handlebars'),
path = require('path');
var app = express();
app.engine('html', consolidate.handlebars);
app.set('view engine', 'html');
app.set('views', path.join(__dirname, '/views'));
var partials = function() {
return {header: '_header', footer: '_footer'};
}
app.get('/', function(req, res) {
res.render('index', {partials: partials()});
};
app.get(/^\/([\w-]+)\/$/, function(req, res) {
res.render('article', {partials: partials()});
};
Not really elegant, but I don't think there is really a way to keep it simpler.

Categories