Using EJS in Express - node.js

My EJS files are in a views folder which is defined in the app.js file as follows:
app.set('views', path.join(__dirname, 'views'));
But currently every time I add a new page I have to specify the route as follows:
/* GET login page */
router.get('/login', function(req, res, next) {
res.render('index', { title: 'Express' });
});
Where router is express.Router(). Is there a better way? I can't believe I need to add this routing code for every page. What's the best practice for EJS?

Related

How to use route for html file already served as static

I use passport.js to authenticate user after he enters login page. To keep user logged in when he returns to home page i'm going to use something like:
app.use(express.static(__dirname + '/public'));
app.get('/', function(req,res){
if(req.user){
// connect to database ....
} else{
res.sendFile(__dirname +'/index.html');
}
});
Note that index.html file is inside "public" folder. Recently i realized that having a code like above, node.js doesn't use app.get('/'....) route but it serves index.html directly. So i'm unable to check if req.user exists. Any suggestion?
As You might understand express.static handles index.html before Your router.
But You cannot avoid express.static also (otherwise You have to use nginx or write own static file output).
So You've to re-think Your folder structure or have to develop 2 separate apps: api (backend) and frontend (that will request to api for data)
In context of Your question I wrote an example app where I organize assets, html files and app routes:
1) Have such folder structure:
2) and example app.js :
'use strict';
const express = require('express');
const app = express();
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
app.set('trust proxy', 1);
// attaching renderer
app.engine('.html', require('ejs').renderFile); // ejs renderer will render .html files as ejs files
app.set('view engine', 'html'); // views has .html extension
app.set('views', __dirname + '/public'); // views live in public folder
// attaching common middlewares
app.use('/assets', express.static('public/assets')); // our static assets will live in public/assets folder
app.use(cookieParser());
app.use(bodyParser());
// implement and attach passport auth somewhere (:
// remove it after passport has been attached:
const authorizeUser = (req, res, next) => {
req.user = {id: 1, username: 'test'};
next();
};
app.get('/', authorizeUser, (req, res) => {
res.render('index', {user: req.user}); // render get index.html from views folder (see above)
});
app.listen(8080, () => {
console.log('App listening');
});
p.s. download example app from here (don't forget to call npm i inside extracted folder (; )
p.s. implement passport.js Yourself

Node.js / Express app not returning the correct EJS page

I am building a website using Node.js, Express and EJS. For now I have two EJS templates, each corresponding to a page on the website:
the home page URL should be / or /home. The "staff" URL should be /staff. The home one works fine, but for some reason even when I visit the /staff or even a nonsense address (e.g., /eduwshduhwudhwud) I still get the home page. Here is my code that's inside the app.js which is used to build the routes.
Here is my folder structure and code:
var express = require("express");
var app = express();
app.use(express.static("public")); // To allow static files
app.set("view engine", "ejs");
// -------------------------------- HOME PAGE-----------------------------------
app.get("/", function(req, res){
res.render("home");
});
app.get("/home", function(req, res){
res.render("home");
})
// -------------------------------- STAFF PAGE-----------------------------------
app.get("/staff", function(req, res){
res.render("staff");
});
// -------------------------------- HOME PAGE-----------------------------------
// -------------------------------- HOME PAGE-----------------------------------
// -------------------------------- HOME PAGE-----------------------------------
app.listen(process.env.PORT, process.env.IP, function(){
console.log("SERVER IS RUNNING!");
})
Use path.join(__dirname, 'views') to combine the application's directory (i.e., _dirname) to your views directory.
This is how I am doing it in my application:
var express = require('express');
var path = require('path');
...
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views')); // <-- add this line before your view engine definition
app.set('view engine', 'ejs');
...
Given this, within my routes I can refer to any view in the views folder with res.render(). For example:
res.render('dashboard', { title: 'My App', greeting: 'Hello' });

"ejs.render" is calling next route

when I enter in http://localhost/client, display 404.
app.get('/client', function(req, res) {
...
ejs.render('any template', {});
...
res.end();
});
app.get('*', function(req, res) {
console.log('404');
...
});
but if I remove "ejs.render" and put res.end('any html') works.
How can i use "ejs.render" and not call 404? Thanks. It's a bug.
You need to set ejs for use EJS with express.
The Express application generator uses Jade as its default, but it also supports several others (Like ejs, pug, etc).
For example:
var express = require('express');
var app = express();
// set the view engine to ejs
app.set('view engine', 'ejs');
// use res.render to load up an ejs view file
// index page
app.get('/client', function(req, res) {
res.render('pages/index'); //does not needs ejs extension
});
app.get('*', function(req, res){
res.send('what???', 404);
});
app.listen(8080);
console.log('8080 is the magic port');
When you make a request to the home page, the index.ejs file will be rendered as HTML.
See the official documentation here.

How do I render a HTML file in a subfolder?

Within my "views" folder, i have another folder inside called "partials" that has other html files i'd like to render.
I thought it'd be self explanatory but searching through google I can't find the answer to this, but I'd like to render a file within the subdirectory as well.
I'm sure the answer is rather simple but I can't seem to find it..
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'html');
app.engine('html', require('ejs').renderFile);
var router = express.Router();
//This Works
router.get('/', function(req, res, next) {
res.render('index');
});
//This Works
router.get('/about', function(req, res, next) {
res.render('about');
});
//This Does NOT Work, How do I get this to work?
router.get('/partials/navbar', function(req, res, next) {
res.render('/partials/navbar');
});
Maybe just remove the first / from res.render('/partials/navbar')

Render jade template from middleware in node.js with express

Instead of checking in every controller I want to use app.all('*') to check if the user is authenticated and it already works quite well. If the user is logged in I'm just calling next() and if he's not I'm calling another route to display the login page.
So far so good, but it seems that rendering from that middleware callback function somehow messes up my paths, for example the stylesheet doesn't work and when I click on it in the page source I again land on the index page.
To sum it up, this works and displays my styles:
app.get('/', function (req, res) {
res.render('index', { title: 'Account Page' });
});
while this does work partially, it only displayes the HTML without the styles from the stylesheet:
app.all('*', function (req, res) {
app.set('loggedIn', controller.security.authenticationAction(req));
if (app.get('loggedIn')) next(); // go on with '/' route
else res.render('index', { title: 'Index Page' });
});
This also displays the same HTML page (with another title though) just without the styles.
This is my default config in the app.js:
app.all('*', function (req, res) { ... });
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.cookieParser('keykeykey'));
Help!
Your stylesheets are (probably) served by express.static, which is declared after your app.all() route (with Express, whenever you first declare a route, the router middleware is inserted into the middleware chain there-and-then; in fact, using app.use(app.router) is useless most of the time, because Express has already inserted it behind the scenes).
Because requests are processed by middleware in order of their declaration, your app.all gets to handle the requests for static resources as well. Try moving the static middleware to before your app.all:
app.use(express.static(path.join(__dirname, 'public')));
app.all('*', function (req, res) { ... });
By the way, express.favicon() would probably give similar issues, and if you want to use any of the services provided by express.bodyParser or express.cookieParser etc., the same applies again).

Resources