expresspugconnect-flash

Connect flash not displaying messages in Pug


I have an application with several routes, and I want to send flash messages of different kinds given the user interaction: either a success or failure message, or in some cases no message. Right now the messages are not displaying and I can't figure out how to get it to work. I'm using Node, Express and Pug.

I have a server.js file, routes.js file, message.pug file, and layout.pug file. Here are my files:

server.js

// init project
const express = require('express');
const app = express();
const bodyparser = require("body-parser");
const flash = require('connect-flash');
const passport = require("passport");
const session = require("express-session");

// http://expressjs.com/en/starter/static-files.html
app.use(express.static("public"));
app.set('view engine', 'pug');

// bodyparser middleware
app.use(bodyparser.urlencoded({ extended: false }));
app.use(bodyparser.json());

// express-session middleware
app.use(session({
  secret: process.env.SECRET,
  resave: true,
  saveUninitialized: true
}));

// express-messages middleware
app.use(flash());
app.use((req, res, next) => {
  res.locals.messages = require('express-messages')(req, res);
  next();
});

app.use(express.json());

// import passport-config file
require("./passport-config")(passport);

// passport middleware
app.use(passport.initialize());
app.use(passport.session());

const routes = require('./routes.js');
routes(app);

// listen for requests :)
const listener = app.listen(process.env.PORT, () => {
  console.log('Your app is listening on port ' + listener.address().port);
});

routes.js

app.get('/', (req, res) => {
  req.flash("success", "your flash messages are working");
  res.redirect("/admin");
});


app.get("/admin", (req, res) => {
    res.render(process.cwd() + '/views/pug/admin');
  });

message.pug

.messages
  each type in Object.keys(messages)
    each message in messages[type]
      div(class="alert alert-" + type) #{ message }
      // expected output
      // div(class="alert alert-success") your flash messages are working

layout.pug

div.col-10.ml-sm-auto.px-4
  != messages('message', locals)

Solution

  • Since I had only two types of messages I was sending -- success or error -- I got rid of my messages.pug file and used the following code, which works.

    server.js

    // init project
    const express = require('express');
    const app = express();
    const bodyparser = require("body-parser");
    const flash = require('connect-flash');
    const passport = require("passport");
    const session = require("express-session");
    
    
    // http://expressjs.com/en/starter/static-files.html
    app.use(express.static("public"));
    app.set('view engine', 'pug');
    
    // bodyparser middleware
    app.use(bodyparser.urlencoded({ extended: false }));
    app.use(bodyparser.json());
    
    // express-session middleware
    app.use(session({
      secret: process.env.SECRET,
      resave: true,
      saveUninitialized: true
    }));
    
    // express-messages middleware THIS IS WHAT I CHANGED
    app.use(flash());
    app.use((req, res, next) => {
      res.locals.errors = req.flash("error");
      res.locals.successes = req.flash("success");
      next();
    });
    
    app.use(express.json());
    
    // import passport-config file
    require("./passport-config")(passport);
    
    // passport middleware
    app.use(passport.initialize());
    app.use(passport.session());
    
    const routes = require('./routes.js');
    routes(app);
    
    // listen for requests :)
    const listener = app.listen(process.env.PORT, () => {
      console.log('Your app is listening on port ' + listener.address().port);
    });
    

    routes.js (the same as before)

    app.get('/', (req, res) => {
      req.flash("success", "your flash messages are working");
      res.redirect("/admin");
    });
    
    
    app.get("/admin", (req, res) => {
        res.render(process.cwd() + '/views/pug/admin');
      });
    

    Then in layout, I use the following:

    div.col-10.ml-sm-auto.px-4
        if successes
          for success in successes
            div.alert.alert-success #{ success }
        if errors
          for error, i in errors
            div.alert.alert-danger #{ error }
    

    This works for displaying a message in a redirect.

    Note: If you want to display a message directly (via res.render()), you have to pass it to the render method directly like this:

    app.get('/admin', (req, res) => {
      req.flash("success", "flash message for a render method");
      res.render("/admin", { successes: req.flash("success") });
    });