node.js Express - How to get partial views asynchronously - node.js

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 }
});
});
};

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.

Point all URLs to a single web page with node.js + express + jQuery

I just started experimenting with node & express, and am trying to load the content of various HTML files into a single web page with Ajax.
I want the URL shown in the address bar to reflect the actual file structure on my server; so for instance when a user clicks a link with href="posts/thePost.html", instead of actually going to that page, I use click(), preventDefault(), and Ajax to load the content in a div, then pushState() and window.onpopstate to make the address bar show the relative path of the file. I do not want to use the hash (#) symbol or queries (?=) or anything like that, I want normal URLs.
This works fine, but when I refresh the page, the file located at the URL (i.e. posts/thePost.html) is displayed instead of index.html with the loaded content. Is there a way to use node to fix this, maybe by intercepting the request and displaying the content of index.html instead? I've tried to search this but haven't been having any luck.
Sorry if this sounds confusing. In short, the behavior that I'm looking for is that no matter what URL the address bar shows when the page is refreshed, index.html should be served up instead.
That's rather easy to do:
function serveIndex(req, res) {
return res.sendfile('index.html');
}
app.get('*', serveIndex);
app.head('*', serveIndex);
You'll likely want to put this after your other routes so you don't end up clobbering them.
var routes = require('./routes/index');
app.use('/',routes);
app.use('/index',routes);
function serveIndex(req, res) {
res.redirect('/');
}
app.get('*', serveIndex);

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.

Blocks and Extends in Jade layouts with Express not functioning

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.

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

Resources