node, express, jade: How to process form data - node.js

Is there any best practise code pattern how to process HTML form data with express and jade templates? I was wondering, if it would make sense to use a PHP like self calling loop of the form template, say in your router script you have two handler for the same route, one for GET and the other for POST requests. Something like:
exports.getHandler = function(req, res){
res.render('/formhandling/', {mode: "form-filling"});
}
exports.postHandler = function(req, res){
res.render('/formhandling/', {mode: "form-processing"});
}
and the jade template might look like
extends layout
block content
h1 #{title}
if mode == "form-processing"
p Form data processed...
else
form(name="", method="post", action="/formhandling/")
...
Does that make any sense or did I get something completely wrong?

I feel like you could just use jQuery to hide the form after the user submitted, instead of rendering the response again. If you want to do any processing of the form on the server side, you can do that in your app.js.
app.get('/', routes.form);
app.post('/', function(res,req){
/* form processing here
you could also do this with an external route */
});
Edit: Also, see my answer on this question

Related

How to send a file into an iframe with node-express?

I want to load a html file into an iframe, with express. A have a < a > tag, and when I click on it, the iframe appears. The frame loads, but I obviously get a "CANNOT GET" message in it, because I don't have the appropriate routing. I have the following code snippets.
index.html:
<a id="ASZF">Adatvédelmi Szabályzat</a>
<iframe id="ASZFframe" src="ASZF.html"></iframe>
server.js:
app.get("/ASZ",function(request, response){
response.sendFile(path.join(__dirname+"/ASZ.html"));
});
Should I use < a href="?" >, or something else?
Your express is not made aware of that route. Your route should be:
app.get("/ASZF.html", function(req, res) {...});
But you probably want to look into serve-static instead of creating a controller just for this.

Render 2 templates at the same time on Node/Express

I come from the PHP scenario, so this may be a wrong question.
I serve a page (templates with Handlebars) to client this way:
router.get('/', function(req, res) {
res.render('home');
});
and it works, but what if I need to divide my template in some different parts (so I'm able to reuse one of this in many different way)? For example, I have a template for header and one for footer.
Something like this:
router.get('/', function(req, res) {
res.render('header');
res.render('content');
res.render('footer');
});
How can I achieve this? Thanks.
Assuming you are using handlebars template rendering service, you can use partials.
http://handlebarsjs.com/partials.html
Code example: https://github.com/donpark/hbs/blob/master/examples/partial/views/index.hbs
The basic high level call stack follows like this:
res.render('page') ---> parses N of partials (recursively) --> html out

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.

Rendering menus as Jade view partials in Express

I'm having trouble conceptualizing how to render menus with active states in an Express app using Jade view partials.
I have something like this:
ul.menu
li
a(href='/some/route').active
li
a(href='/another/route')
What I'd like is for the .active class to be applied to the current route, so my CSS can render an active UI state.
When I wrote in PHP, this would've been accomplished through some complex chain of if/else, statements, but I'm assuming there's a more elegant approach. What am I missing?
My solution is similar to danmactough's, but I think a little tidier.
I use middleware to save the url as a local variable on all requests. Make sure this comes before your routes.
app.use(function(req, res, next) {
res.locals.url = req.url;
next();
});
My Jade template for a menu looks like this
ul
each link in links
li
a(href=link.url, class=link.url === url && 'active')= link.name
Jade is ignorant about the route. I don't think there's any way to avoid the if/else in one form or another.
In Express, just pass the route as a local:
res.render('my_view', {
current: 'current/url'
});
And in the view, have an array of menu links and do something like:
ul.menu
for each item in links
li
if (item.url == current)
a(href=item.url).active
else
a(href=item.url)

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