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

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.

Related

how can we define static variable and call in html file in node.js?

I want to define variable in app.js file then after use this variable in whole/any html page.
Fore example:
app.js
var title = 'mytask';
index.html
<%=title%>
You can easily do the same using ejs
But if you want to use the varibale on hmtl page, you need to pass the title while rendering the page .
Say there is an "index.html"
res.render("index", {title :title});
now you can easily use the title variable in index.html
<div>{{title}}</div>
What you're looking for is called a local variable. If you're using Express (which I assume you do), then you have two kinds of locals, which are both sent to the views automatically, without passing them manually in each of your routes:
app locals: these are alive persistently for the entire lifetime of the application, you can use them anywhere where the app object is in scope. (more info)
response locals: these are tied to the lifecycle and scope of a single request/response object (more info)

rendering some dynamic blocks on page - express.js + jade

Looking for a solution for a few days. Need help.
Source:
node.js + express.js + jade template engine
Problem:
Can't understand how I can render 1+ dynamic blocks on one page.
For example:
We have a page: News main page
Blocks on page: Latest news (list 20 itens), hot news (list 4 items), most viewed news (4 items), block with news categories (it can display current category on the page with page with card of one selected novelty, so it is dynamic block too), and block with some user auth data.
"block" i mean a widget as we can see on site, not a block of code.
What can I do in express? I can route special url to special function in routes.
So as I see, if a want to render all this blocks on the one page I have to call all functions rendering each block in only one function of route.
I mean it seems that I have to do something like this (sure in libs but doesn't matter here)
app.get('/news', function(req, res){
call_last_news(funcion(){
call_hot_news(function(){
call_get_user_info(function(){
...
...
...
template.render.here();
final_here();
});
});
});
});
This looks real but so unuseful and unsupportable code that .. That's bad.
I can see solution in calls from template engine to render some blocks on the page. But not just include because all blocks can use db or cookies, session data etc. all blocks are dynamic. But I have no idea how to create such engine using express.js + jade
Well I'm not certain I understood all of the problem but based on the pseudo code, it looks like the main concern here is that you have a deeply nested set of potentially independent and reusable functions. There are two approaches to this problem that come to mind:
Use a control flow library
Use something like async series, parallel, etc. (which function depends on the nature of your code – are all of the call_ functions independent?) That will clean up your code and make it more maintainable.
Use ajax
Another approach you can take is to quickly render the page without all of the call_ functions and just make several ajax calls from the client to fill in the data. You could have routes which look like '/news/last', and '/news/hot', etc. This is nice because you can separate out all of the logic for each of these units into reusable URLs so you can mix and match them on any page.

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

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