In Express/EJS, how do I change the default layout? - layout

I don't want it to be layout.ejs.
I want to set my layout to be another template for THIS specific controller.

Try using:
app.set("view options", { layout: "mylayout.jade" });

Use the layout option to res.render()
res.render('page', { layout: 'mylayout.jade' })

Set custom default layout
Just set layout property in express app settings.
app.set('layout', 'layouts/layout');
Set custom layout for single render
Just pass layout as render locals object.
app.get('/', function(req, res) {
res.render('the-view', { layout: 'specific-layout' });
);
More info here: https://www.npmjs.com/package/express-ejs-layouts

Providing you're using the Ejs-express-layouts module you can specify a layout for a particular view, overriding the default:
app.get('/', function(req, res){
res.render('aView', { layout: 'someSpecificLayout' })
})

Related

How to routing for mobile view in express

I want to change the URL for mobile. www.example.com to m.example.com
I use isMobile function to detect device type.
I do not know what to do for routing.
for example: m.example.com/index
please help me
in app.js
function isMobile(req, res, next) {
if ((/Android|webOS|iPhone|iPad|iPod|BlackBerry|BB|PlayBook|IEMobile|Windows Phone|Kindle|Silk|Opera Mini/i.test(req.headers["user-agent"]))) {
res.redirect('//m.' + req.host+ req.path);
} else {
next()
}
}
app.get('/',isMobile,routes.index);
If device is a mobile,i want to run routes.mobileindex. How?
If you want to render a separate view for mobile devices in the same application then it would be pretty straigh forward. it is a just a matter of creating another view file and you can apply your separate layout and CSS style to design it.
var express = require("express");
var router = express.Router();
function isMobile(req, res, next) {
if (
/Android|webOS|iPhone|iPad|iPod|BlackBerry|BB|PlayBook|IEMobile|Windows Phone|Kindle|Silk|Opera Mini/i.test(
req.headers["user-agent"]
)
) {
// Instead of redirecting to another view you can also render a separate
// view for mobile view e.g. res.render('mobileview');
res.redirect("/mobile/device");
} else {
next();
}
}
/* GET home page. */
router.get("/", function(req, res, next) {
res.render("index", {
title: "Express"
});
});
router.get("/device", isMobile, function(req, res, next) {
res.json("normal view is rendered");
});
router.get("/mobile/device", function(req, res, next) {
res.render("mobile");
});
module.exports = router;
I have set a redirection here but this is not the best way if you are in the same application, because you can directly hit /mobile/device view, in that case you also need a middleware or can reuse the isMobile middleware to redirect to normal view. I would rather suggest to use res.render('yourviewname')
Hope this gives you an idea to proceed futher!

Do I need to send common variables in every get call in nodejs?

I have a bunch of pages in my express project. The navigation (which occurs in all pages) contains the user's name if they're logged in. Do I need to pass the user variable every time to each page or is there a better way of doing this?
For instance:
router.get('/', function(req, res) {
res.render('index', { title: 'Index!', user: req.user });
});
router.get('/helloworld', function(req, res) {
res.render('helloworld', { title: 'Hello World!', user: req.user });
});
...
As already mentioned by #robertklep in the comments, I'll expand on it a bit.
There's app.locals which sets variable for all requests. You can set it outside your router. This is usually for setting site-wide variables like title of the site.
app.locals.title = 'My Site'
Then there's res.locals which is for setting variables for the specific requests. An example would be to set the user object.
res.locals actually over-rides app.locals in that if a property is found on both then the one on the res.locals takes precedence. For example you can have a site-wide title and then a specific title for a specific route.
app.locals.title = 'My Site'
app.get('/index' function(req, res, next){
res.locals.title = 'Index | ' + app.locals.title;
...
});

How access to app from controller/EJS? Express.js

I want to access to app.routes from my controller or EJS view, but app var don't exists there.
Do you know how can I access to all the routes that I defined myself in config/routes.js?
Thank you.
PS: I'm using sails.js, based on express.js.
You can use request.app:
app.get('/foo', function (request, response, next) {
console.log(request.app.routes);
next();
});
Here is the final solution:
module.exports = {
index: function (req, res) {
return res.view({
layout: 'layout',
title: 'Trip Analyzer',
routes: req.app.routes
});
}
};
EJS view in Javascript:
console.log(<%- JSON.stringify(routes) %>);
Thanks!

Toggle active link Bootstrap navbar

I've read a lot of posts on the subject, found almost always the same solution but it does not work for me...
My problem is as follows : I want to use Twitter Bootstrap 2.3.2 and its navbar, so I include the css and js files. Just before that, I also include jquery. I then take an example given on the bootstrap site which display very well. However, I now want to set the menu item clicked as active and remove the active class from all others. I saw in the bootstrap.js file that this function is built in, so no more script code to include. The problem is that the menu items do never toggle to active. I then tried to add a jquery script to force removing all active classes and add the active class to the one item that was clicked. Nothing happened.
So please, help !! I tried the same code in jsfiddle and it works fine, so does the problem comes from jade ? from express layout ? how to fix it ?
Here is the code I use :
server.js
var express = require('express');
var app = express();
var port = 3000;
app.set('view engine', 'jade');
app.set('view options', {layout: true});
app.set('views', __dirname + '/views');
app.configure(function () {
this.use(express.cookieParser());
this.use(express.session({ secret: 'shhhhhhhhh' }));
this.use(express.static(__dirname + '/public'));
this.use(app.router);
});
app.get('/', function (req, res) {
res.render('index')
});
});
app.get('/about', function (req, res) {
res.render('about')
});
});
app.listen(port, function () {
console.log('listening in http://localhost:' + port);
});
/views/layout.jade
!!! 5
html
head
title Test Application
link(type='text/css', rel='stylesheet', href='/css/site.css')
link(rel='stylesheet', href='//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap.min.css')
script(src='//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js')
script(src='//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js');
body
div.navbar.navbar-inverse.navbar-fixed-top
div.navbar-inner
div.container
button.btn.btn-navbar(type='button', data-toggle='collapse', data- target='.nav-collapse')
span.icon-bar
span.icon-bar
span.icon-bar
a.brand(href='#') Login Test Application
div.nav-collapse.collapse
ul.nav
li.active
a(href='#') Home
li
a(href='#about') About
li
a(href='#Contact') Contact
div.container
block content
/views/index.jade
extends layout
block content
div.span6.offset3
h1 Test Application
div.span12
h2 Test application!
p This is a test application
button.btn.btn-success(type='button', onclick='')') Login
/views/about.jade
extends layout
block content
div.span6.offset3
h1 - About -
You can try with something like that in you jade layout :
li(class=title=='Home'?'active':undefined)
a(href="/") Home
li(class=title=='About'?'active':undefined)
a(href="/about") About
li(class=title=='Contact'?'active':undefined)
a(href="/contact") Contact
Then just add this to your server.js :
app.get('/', function (req, res) {
res.render('index', title: 'Home')
});
app.get('/about', function (req, res) {
res.render('about', title: 'About')
});
This way, you can also remove the hard coded title in your layout and modify it through this solution as :
title #{title} | Test Application
And it will render this as a title for your home :
Home | Test Application
Here the solution I've found (I dont have the link anymore, sorry for the code owner)
ul.nav
-var obj = { 'home':'Home', 'about':'About', 'contact':'Contact' }
-each val, key in obj
-if (id == key)
li.active
a(href='#{key}') #{val}
-else
li
a(href='#{key}') #{val}
and I set the server.js as
app.get('/about', function (req, res) {
res.render("about", {
title: 'About',
id: 'about',
user: JSON.stringify(req.user, 0, 2)
});
});

Node/Express.js - Overriding where to look for the 'Views' folder for each request

In my Node/Express.js project I can set the views folder globally like so:
app.configure(function() {
app.set('views', __dirname + '/views');
.... snip ....
});
...and all my view templates go into the views folder.
Is it possible to override where Express looks for views on a request by request basis? For instance, something like the following:
app.get('/', function(req, res) {
res.render('index', { viewFolder: 'otherViews' });
});
The reason I ask is I'm trying to replicate Microsoft ASP.NET MVC's Areas functionality where each Area gets it's own views folder.
The 'views' setting is the root directory, so you should be able to specify a sub-folder in the hierarchy:
app.get('/', function(req, res) {
res.render('areaName/viewName');
});
It means your 'areas' need to be sub-folders, but it allows you to accomplish the separation you are looking for.
As a more modular solution, I did something like this in sails.js.
Just over-ride the render function for the given request in your middleware. :)
var curRender = res.render;
res.render = function(path, locals, func) {
var args = [res.locals.explicitPath + '/' + path, locals, func];
curRender.apply(this, args);
};
Full path works too
app.get('/', function(req, res) {
res.render(path.join(__dirname, 'view.jade'));
});

Resources