2

Started with Express a couple weeks ago and finally hit my first roadblock. I'm trying to figure out how to send a flash message to my view (layout.jade). When I'm validating a user signup and it fails validation (using express-validator), I want to write to the session flash message and then show it on the page.

What I'm doing now only works if I refresh AFTER POSTing (e.g. in controllers/index.js), and I also need to figure out how to only make this flash message show once:

/app.js

/*
 * Configuration
 */
app.configure(function() {
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(expressValidator);
  app.use(express.cookieParser());
  app.use(express.bodyParser({ uploadDir : './' }));
  app.use(express.methodOverride());
  app.use(viewHelpers());
  app.use(function(req, res, next){
    res.locals.messages = req.session.messages || {};
    delete req.session.messages;
    next();
  });
  app.use(express.session({
    secret: config.secret,
    cookie: {
      maxAge: 365 * 24 * 60 * 60 * 1000
    },
    store: new MongoStore(config.db)
  }));
  app.use(express.static(__dirname + '/public'));
  app.use(app.router);
});

/views/layout.jade:

div.alert.alert-error
  - if (typeof messages !== "undefined")
    !=partial('session_flash', { messages : messages })

/views/partials/session_flash.jade:

div.alert.alert-error
  each message in messages
    =message

/controllers/index.js

req.assert(['user', 'username'], 'Please enter a valid username').len(3, 23);
req.assert(['user', 'email'], 'Please enter a valid email').isEmail();
req.assert(['user', 'password'], 'Please enter a valid password').len(3, 23);
req.session.messages = 'Please fix the errors below';
    errors = req.validationErrors();

    if (errors) {
      console.log(errors);
      res.render('join', {
        title : 'Join -',
        errors: errors,
        params: params
      });
      return;
    }

Is it only showing up after I refresh (after a POST) because I'm rendering the join template from within /controllers/index.js and not /app.js? Also, should I be doing something like delete req.session.messages within my configuration? I couldn't find a complete example of this anywhere and the ones I've found were outdated.

bob_cobb
  • 2,229
  • 11
  • 49
  • 109

1 Answers1

1

Looks like you are indeed using an outdated example. Express v3.x doesn't use partials anymore. See View system changes in the wiki. Instead use blocks and includes.

An easy way to show error messages on login would be

index.js

app.locals.error = null;

app.post('/login', function(req, res){

  var name = req.body.name;
  var password = req.body.password;

  if (!name || !password) {
    res.status(400);
    return res.render('login', {
      error: 'All fields are required'
    });
  }

})

app.locals.error = null sets the default value of the error to null. By doing that you don't have to set the error variable every time you render login.jade and no error is present.

res.render('login', {
  error: null
});

Your login.jade template could look like this

extends layout

block content
  - if (error)
    p= error
  form(method='post', action='/login')
    p
      label(for='name') Username:
      input(type='text', name='name', id='name')
    p
      label(for='password') Password:
      input(type='password', name='password', id='password')
    p
      input(type='submit', value='Submit')
zemirco
  • 16,171
  • 8
  • 62
  • 96