Now, this one might be obvious if you’re experienced with Node.js and Express, but it took me a while to figure out… therefore, so I know where to look the next time I forget it, and as a service to people Googleing in frustration; without further ado:
How to make Express render flash messages
First: Realize that flash messages are messages that are stored on the server for the duration between two requests from the same client, and thus are only available in the next request :D. Don’t try to req.flash(...) stuff and expect it to be available when render ing the view immediately after… (yeah, I did that for some time – pretty stupid, I know)… the locals object is how you do that.
Next: You need to make sure that the cookie decoder and session middleware are active:
1 2 3 4 5 6 7 |
var app = require('express').createServer(); app.configure(function() { // (...) app.use(express.cookieDecoder()); app.use(express.session()); }); |
Then: To store messages to be shown in the next request:
1 2 3 4 5 |
app.post('/someUrl', function(req, res) { req.flash('info', 'Hello there!); req.flash('error', "OH NOES!!!11") res.redirect('back'); }); |
Note how nifty the PRG pattern can be implemented with Express. Note also that flash supports formatters, where the default supports %s and _, e.g.
1 |
req.flash('info', 'You have added _%s items_ to your shopping cart.', count); |
resulting in something like this (with jQuery UI for formatting):
Last: When handling the next request, the flash messages are available in an object that can be retrieved only once by calling flash with no arguments on the request:
1 2 3 |
app.get('/', function(req, res) { res.render('index', {locals: {flash: req.flash()}}); }); |
Now, having passed the flash object to my view, I can do this in my HAML view:
1 2 3 4 5 |
:if typeof flash != 'undefined' :if flash.error %span.error= flash.error :if flash.info %span.info= flash.info |
where the preliminary :if typeof flash != 'undefined' ensures that we don’t get errors if we haven’t transferred the flash object to the locals object.
The only annoying thing is that we need to remember to transfer the flash object in each request handler. I set out to write a piece of Node.js middleware that handled this, and I thought it was going pretty well until I realized that the middleware was executed in the wrong place. I haven’t found out if there’s an appropriate hook that can do this, so if anyone knows, please tell me :).