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 :).
Thanks for this! I was seriously racking my brain on this one. It’s not described at all very well on the expressjs guide.
Thanks very much!!!
I really needed it
Hey mookid, just a quick heads up. You can avoid constantly transferring the flash object by just transferring the request object instead. Just write a middleware that looks like so:
And then, in your templates:
Et voila! Flash is in every template now, without needing to explicitly add it to the locals.
Hi Spyro7,
Thanks – that looks pretty cool!
I actually tried to write a middleware that did something like that, but I think I must have messed it up by trying to invoke flash() on the request before the function was there – but I gather that your code would actually work because it passes the entire request on to the view, thus delaying the call to flash() until the function is there.