Blocks and Extends in Jade layouts with Express not functioning - node.js

I have a small express site written for node. I'm using Jade for layouts, and trying to get a handle on the new extends/block bits. When I use the standard layout/child view pattern list here, everything works great:
https://github.com/visionmedia/express/blob/master/examples/jade/views/layout.jade
I want to get fancy and use blocks to stuff custom html into specific parts of the master layout. So I transitioned over to something that looks more like this:
https://github.com/visionmedia/jade/blob/master/examples/extend-layout.jade
https://github.com/visionmedia/jade/blob/master/examples/extend.jade
Using the exact code in the extend-layout example above, my pages will always render the extend-layout.jade part, but never the content inside. Anything inside of a block never seems to get rendered. I've given this a try, but it doesn't help:
https://github.com/visionmedia/jade/issues/377
I'm running node 0.6.2, express 0.2.5, and jade 0.18. Any takers?

The layout config entry is deprecated now anyway with v3 of Express.
You can only use the block/extends style.

So I've figured out what was up. I was manually specifying the layout to use in express - I was setting it to the correct layout, but removing that line solved the problem. Example (for others who run into this):
exports.index = function(req, res){
res.render('index', { title: 'Express' }) // this works!
res.render('index', { title: 'Express', layout: 'layout' }) // this doesn't work
};
I would have expected a different behavior - including an explicit layout like this simply caused the child view to not render within the master layout.

Related

What does app.engine() do ? And what are ext and callback?

I tried reading through the documentation and they said
app.engine(ext, callback)
Register the given template engine callback as ext By default will require() the engine based on the file extension. For example if you try to render a "foo.jade" file Express will invoke the following internally, and cache the require() on subsequent calls to increase performance.
I am having a tough time figuring out what do ext and callback here even mean.
This is part of the view/template engine functionality of Express. Many times your request handlers only return some JSON object. But other times you want to build a regular "document" like a fully built HTML page, or RSS feed etc. Template engines help you achieve this, though they are by no means mandatory. You could use other approaches (build strings by hand for example, if you like the pain), or you could use a library such as pug/moustache etc by hand. The view engine functionality basically integrates libraries such as pug/moustache into express so it's easier to use them.
The linked page has a nice example of how this would be used in practice:
Then create a route to render the index.pug file. If the view engine property is not set, you must specify the extension of the view file. Otherwise, you can omit it.
app.get('/', function (req, res) {
res.render('index', { title: 'Hey', message: 'Hello there!' })
})
When you make a request to the home page, the index.pug file will be rendered as HTML.
Many times express knows about various template engines. So it's enough to say express.set('view engine', 'pug') and it can do the right thing as long as the pug package is installed.
Other times you need to use app.engine to tell it more explicitly what to do. It is called like app.engine('jade', require('jade').__express). The first parameter is just the extension express should be looking for. So when you say req.render('index', ...) it would look for an index.jade file. The second parameter is the function which actually does the integration between the view engine (which, as I've said, is a separate thing from express), and express itself. consolidate.js is a package with integrations for a lot of view engines.
But if you want to see what this function does, checkout developing template engines for Express. The callback parameter must look like function(filePath, options, callback). filePath is just the name of the disk file to use for rendering, so index.jade in the example from above. callback is a standard node callback, invoked as callback(err) on error or callback(null, renderedContent) on success. options is an object passed in from the req.render('index.jade', /* options */ { title: 'foo', content: 'bar' }). It's then up to you to decide how to actually do the rendering based on the supplied arguments.
In simple terms: ext - extension, callback - library (engine) that will render the file with the given extension.

Heroku not displaying all pug views

I'm making a website, I'm using node and express on the back end, pug on the frontend.
My website is split up into few views via pug.
Layout, I have as the highest view, all of the views "inherits" from there.
So layout ends with
block content
and everything after that starts with:
extends layout
block content
and then rest of the pug code for that view.
I have one view, that is map which inherits from layout but then also has children on it's own.
So the hierarchy is
layout --> map --> content
Locally I have no problem rendering as follows:
router.get('/', function(req, res, next) {
res.render('content');
});
and having the map displaying as well.
When uploading on Heroku however, heroku displays content AND layoutbut not the map!
Even if content starts with
extends map
block content
Does anyone know why heroku does that?
try renaming the content of the map page as mapcontent or similar.

What is the correct way to use express with a second div that needs data

I have the following layout.jade file:
!!! 5
html
head
body
#left
#leftbody
#center
#centerbody
#container!= body
#right
#rightbody
And I have the following route.js file:
app.get('/',
function(req, res) {
Post.find({}).execFind(
function(err, data) {
res.render('post/index', {
posts: data
});
});
});
I'm currently rendering #centerbody based on links in the #leftbody. I'm wondering how I could use express to populate the #rightbody. Currently I'm populating a ul in #rightbody using an ajax call in document.ready but was wondering if there was another way using express.
I would strongly advise you to have a look at Jade includes, or, even better, Jade template inheritance
This would allow you to keep, for all your pages, the common parts of the page in separated files. And allow easier maintenance. This is definitely the thing to do.

Emulating the 'layout' functionality of Jade while using Mustache

I setup node and express then integrated the mustache.js template by following the instructions on this page:
http://bitdrift.com/post/2376383378/using-mustache-templates-in-express
So far so good, except I'm having a lot of trouble trying to setup mustache.js to have the same functionality as Jade's "layout". I'm basically trying to setup 1 master file to serve as a shell for my other pages similar to extending a template with Django.
Ex. The layout file could have this:
[html]
[title]my title[/title]
[body]{{content}}[/body]
[/html]
Where {{content}} gets replaced with the contents of a file which I would specify somehow in the route for that page.
I just have no idea how to set this up with express because I'm still a huge newbie with it and the way it's setup with Jade is automagical which seems to be specific to Jade only.
With Jade you just need to make a "layout.jade" file and have something like this as your route:
app.get('/', function(req, res) { res.render('home', { title: 'My home page' }); });
Then it magically adds the contents of home.jade into your layout.jade file wherever you specified the body!= body tag.
So yeah, how can I set something like that up with Mustache? If you know the answer please explain it step by step.
You could write a stache renderer plugin for docpad

node.js Express - How to get partial views asynchronously

I've got a layout - navigation menu. In express tutorials theres only old-school pages loading. whole old page is thrown away and a new one is downloaded with all layouts,views and partial views. And i want navigation menu to stay. So how can i do that?
If i'm maybe getting smth wrong with this web pages architecture please guide me.
As #drachenstern said, you want to render only partial HTML fragments, not whole documents including the layout. You can tell express to skip the layout using:
res.render('sometemplate', {layout: false});
If you want to look for Ajax requests as distinct from full-page browser loads, use the req.xhr flag as documented here
Thus you might even be able to do
res.render('sometemplate', {layout: !req.xhr});
You can also use res.partial() which is specifically for rendering partials.
Here is a sample of its usage, where 'browse.jade' is name of the template:
exports.browse = function(req, res){
var Contact = mongoose.model('Contact');
Contact.where({}).asc('surname', 'given_name', 'org').run(function(err, results) {
res.partial('browse', {
locals: { data: results }
});
});
};

Resources