Jason Chen Jason Chen - 3 months ago 57
Javascript Question

Using express-flash with Handlebars?

I am following a tutorial that uses ejs5. That tutorial wants me to use express-flash, and organize my

routes/users
page like so.

router.get('/signup', function(req, res, next){
res.render('accounts/signup', {
errors: req.flash('errors')
});
});


The subsequent es5 goes something like so:

<% if (errors.length > 0) { %>
<%= errors %>
<% } %>


For myself, I am instead using Express-Handlebars. Now, I know that my
app.js
file has everything it needs, since my routing to
/signup
works like so:

router.get('/signup', function(req, res, next){
res.render('accounts/signup');
});


However, if I reformat my router code as shown in the first example, I get a 404 error on my
signup
route. I do not understand why that is. To demonstrate, this is what I have, identical to the first example.

//render the signup//
router.get('/signup', function(req, res, next){
res.render('accounts/signup', {
errors: req.flash('errors')
});
});


To be sure, my main app.js file contains the following:

var flash = require('express-flash');
app.use(flash());


In addition to this, I am also unsure how to replicate the ejs script using Handlebars. Would doing something like this work?

{{#if errors.length > 0}}
{{errors}}
{{/if}}


I am unable to test this as I first need to get my sign up route showing.

Answer

You can register a flash helper and use that in the main template.

// set context for the req, res
app.use(require('./../web/helpers/view').setContext);

exphbs.create({
    extname      :'hbs',
    layoutsDir   : '/path/',
    defaultLayout: 'main',
    helpers      : require('/path/to/view').helpers, // this is where you can register a helper.
    partialsDir  : [
        '/path/'
    ]
});

In view.js, write a method to build html out of the flash message.

'use strict';

const _ = require('lodash');

let  _req, _res;

// build html for flash messages. 
function renderFlashMsg() {
    let flash = _req.flash(),
        out   = '',
        types = ['success', 'error', 'info'];

    _.each(types, (type) => {
        if (flash[type]) {
            out += '<div class="flash-msgs '+ type +'">';
            out += '<h2><span>' + type + '</span></h2>';
            out += '<ul>';

            _.each(flash[type], (msg) => {
                out += `<li>${msg}</li>`;
            }) ;

            out += '</ul></div>';
        }
    });

    return out;
}

module.exports = {
    'setContext': (req, res, next) => {
        _req = req;
        _res = res;
        next();
    },
    'helpers': {
        renderFlashMsg
    }
};

Now you have can just use renderFlashMsg in your main layout file.

Put {{{renderFlashMsg}}} where you want the flash messages to be placed in the DOM.