58

So my web application requires authentication, and I have a signup page where if the person tries to sign up with an email that is already in the database, I want to show them an error message. I'm trying to do this using this code on the html side:

 <% if (message.length > 0) { %>
   <div class="alert alert-danger"><%= message %></div>
 <% } %>

And doing this in my routes:

router.get('/signup', function(req, res) {
  res.render('/signup', { message: req.flash('signupMessage') });
});

I've tried setting up the config with something along the lines of:

app.configure(function() {
 app.use(express.session({ secret : 'keyboard cat' })); 
});

But this gives me a TypeError:

 12:11:38 web.1  | app.configure(function() {
 12:11:38 web.1  |     ^
 12:11:38 web.1  | TypeError: Object function (req, res, next) {

I'm really confused, because I know I need sessions to be working for flash to work, but sessions don't seem to be working for me. I've also tried using only sessions and no flash, by using req.session.messages, but since I don't have sessions working this obviously did not work.

Any insights? I'm using Express 4.0.0 Thanks

Divyanshu Maithani
  • 13,908
  • 2
  • 36
  • 47
BHendricks
  • 4,423
  • 6
  • 32
  • 59

7 Answers7

104

This Gist should answer your question:

https://gist.github.com/raddeus/11061808

in your application setup file:

app.use(flash());

Put that right after you set up your session and cookie parser. That's really all you should need to use flash.

You are using:

req.flash('signupMessage', anyValue);

before redirecting to /signup right?

Here's a fun little tidbit that I currently use for a personal site(in my main application file):

app.use(function(req, res, next){
    res.locals.success_messages = req.flash('success_messages');
    res.locals.error_messages = req.flash('error_messages');
    next();
});

Now every view will have access to any error or success messages that you flash. Works well for me.

One final thing (this is nitpicky but you may gain some knowledge). If you change:

<% if (message.length > 0) { %>

to:

<% if (message) { %>

It will work the same way but will not fail if message is undefined. undefined and empty strings are both considered "falsy" values in javascript.

EDIT: My cookie/session/flash setup goes as follows:

app.use(cookieParser('secretString'));
app.use(session({cookie: { maxAge: 60000 }}));
app.use(flash());

Maybe seeing your application setup code would help. Also note that using app.configure is no longer necessary in Express 4.

Final edit: https://gist.github.com/raddeus/11061808

That is a working example. Go to localhost:3000 after running that app and you should see ['it worked'] on your screen.

Thad Blankenship
  • 2,242
  • 3
  • 16
  • 16
  • But my session and cookie parser set up gives me errors, and yes I am using that call to redirect to /signup – BHendricks Apr 18 '14 at 19:39
  • So I just added those lines instead of my configuration, and I now go back to the error Error: Most middleware (like cookieParser) is no longer bundled with Express and must be installed separately. Please see https://github.com/senchalabs/connect#middleware. – BHendricks Apr 18 '14 at 19:46
  • @BHendricks Then add `var cookieParser = require('cookie-parser');` to the top of your file. And run `npm install --save cookie-parser` – Thad Blankenship Apr 18 '14 at 19:47
  • I have that and have done that, and still get that same error :/ – BHendricks Apr 18 '14 at 19:50
  • @BHendricks I added a fully working gist. Make sure you install dependencies using npm before running it. Note that it will not respond over http but should log the flash message to your console. – Thad Blankenship Apr 18 '14 at 20:01
  • So I have the var cookieParser, what is the value for var session? Is it connect-session, or just require('session'). Thanks – BHendricks Apr 18 '14 at 20:02
  • Session should be bundled with express still I think. I also updated the Gist, use the new one(it actually responds). – Thad Blankenship Apr 18 '14 at 20:03
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/50987/discussion-between-thad-blankenship-and-bhendricks) – Thad Blankenship Apr 18 '14 at 20:08
  • @ThadBlankenship Thanks for the gist. I found you can have some parity with the `express-flash` module if you [add a small middleware method](https://gist.github.com/droppedonjapan/344380bd7857233f1eae) (since `req.flash()` returns an object with the keys being the flash type). – AlbertEngelB Jun 02 '14 at 21:46
  • This is not working with AJAX i guess? I have page that posts AJAX to endpoint which saves to db, I would like to notify user how that went, but the flash-message is never shown. I think it's because the page is never reloaded...? – olefrank Sep 23 '16 at 20:28
28

https://gist.github.com/brianmacarthur/a4e3e0093d368aa8e423

I, too, was initially confused by flash messages in Express 4. The confusion for me arose partly from the distinction between the concept of flash messaging, a temporary message available to a template, and the various implementations of flash messaging, which include express-flash, other modules, and custom middleware.

Just to expand on the excellent response from Thad Blankenship above, I created a Gist for the beginner that includes two approaches to flash messages--the express-flash module and custom middleware--rendered in jade, ejs, or handlebars.

The readme includes details about the getter--req.flash(type)--and setter--req.flash(type, message)--methods exposed by express-flash and how they differ from the exploitation of the res.locals and req.session objects exposed by express-session in the custom middleware.

Poison Oak
  • 671
  • 8
  • 9
14

To show flash message you have to install flash module in your project using cmd.

npm install express-session --save

npm install cookie-parser --save

npm install connect-flash --save

Now you have to add some code to the app.js file to access those modules. Let’s add these code.

var session = require('express-session');

var cookieParser = require('cookie-parser');

var flash = require('connect-flash');

var app = express();

app.use(cookieParser('secret'));

app.use(session({cookie: { maxAge: 60000 }}));

app.use(flash());

Now generate flash message

req.flash('success', 'Registration successfully');
res.locals.message = req.flash();

To show the flash message in view file use the code

<% if(locals.message){ %>
    <div class="alert alert-success" role="alert">
        <strong>Well done!</strong> <%=message.success%>
    </div>
<% } %>
Flexo
  • 87,323
  • 22
  • 191
  • 272
  • 2
    I was wondering how we can make sure that the front-end knows wherever it is a `success` message or an `error` – John John Feb 17 '20 at 05:02
2

After researching for two days and wanting to give up A LOT I've finally found out how to use connect-flash (u do not need cookie-parser) a few main things use (return res.redirect) instead of res.render it does not like render for callbacks I don't know why. Take a look at my code to get a visual.

app.js

var express                 = require("express"),
    bodyParser              = require("body-parser"),
    mongoose                = require("mongoose"),
    passport                = require("passport"),
    LocalStratagy           = require("passport-local"),
    User                    = require("./user"),
    passportLocalMongoose   = require("passport-local-mongoose"),
    flash                   = require('connect-flash'),
    app                     = express();
    //using express-session
app.use(require("express-session")({
    secret:"The milk would do that",
    resave: false,
    saveUninitialized: false
}));
app.use(flash());

app.use(function(req, res, next){
    res.locals.message = req.flash();
    next();
});


//connectiong to a specific database
    mongoose.connect("mongodb://localhost/LoginApp");


    //so body-parser works
app.use(bodyParser.urlencoded({extended: true}));

//making it so express uses the public dir
app.use(express.static("public"));

//setting the view engine to ejs
app.set("view engine", "ejs");


// so passport works
app.use(passport.initialize());
app.use(passport.session());

//authenticated data from the login form
passport.use(new LocalStratagy(User.authenticate()));

//reading the data and encoding it
passport.serializeUser(User.serializeUser());

//reading the data and unencoding it
passport.deserializeUser(User.deserializeUser());


//ROUTES
app.get("/", function(req, res){
    res.render("index");
});


// AUTH ROUTES

//show login
app.get("/login", function(req, res){
    req.flash("error", "")
    res.render("Login");
});

//handle login form data
app.post("/login", passport.authenticate("local",{
    failureRedirect: "/login",
    failureFlash: true,
}) ,function(req, res){
    req.flash("success", "Logged in");
    return res.redirect("/");
});

//Show signup form
app.get("/signup", function(req, res){
    res.render("Signup");
});

//handle signup form data
app.post("/signup", function(req, res){
    User.register(new User({username: req.body.username}), req.body.password, function(err, user){
        if(err){
            req.flash("error", err.message);
            return res.redirect("/signup");
        }
        passport.authenticate("local")(req, res, function(){
            req.flash("success", "successfuly Signed up");
            return res.redirect("/");
        });
    });
});



app.listen(3000, function(){
    console.log("server started");
});

Header.ejs

  <!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
        <meta name="description" content="Fully responsive project with a backend">
        <link rel="stylesheet" href="main.css">
        <script src="https://code.jquery.com/jquery-3.4.0.min.js"></script>
        <!-- animated css -->
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.7.0/animate.css">

        <!-- Bootstrap CSS -->
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
        <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css" integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf" crossorigin="anonymous">
        <title>wire frame chal</title>
    </head>
    <body>

        <h1><%= message.error %></h1>
        <h1><%= message.success %></h1>

Login.ejs

   <% include ../partials/header %>
<form method="POST" action="/login">
    <input type="text" name="username" placeholder="username">
    <input type="password" name="password" placeholder="password">
    <button>Submit</button>
</form>


<% include ../partials/footer %>

Signup.ejs

  <% include ../partials/header %>

<form method="POST" action="/signup">
    <input type="text" name="username" placeholder="username">
    <input type="password" name="password" placeholder="password">
    <button>Submit</button>
</form>


<% include ../partials/footer %>
1

This might be an old post guys but I just became aware of express-flash-2. It appears to be less buggy with Express 4 seems to have solved all my problems.

npm link

Adrita Sharma
  • 21,581
  • 10
  • 69
  • 79
tichy255
  • 69
  • 6
0

In my case if i put the message display part in another EJS file and import it in my layout, i get the success and error both displayed initially without any text since the pager just loaded

_message.ejs

<% if(success_msg) { %>
    <div class="alert alert-success">
        <%= success_msg %>
    </div>
<% } %>

<% if(error_msg) { %>
    <div class="alert alert-danger">
        <%= error_msg %>
    </div>
<% } %>
Abhinav
  • 21
  • 4
0

The easy-to-use, although unmaintained, "express-flash-messages" package worked for me. See code here: https://github.com/s2t2/express-app-prep-2021/pull/1/files

App Config:

var session = require('express-session')
var flash = require('express-flash-messages')

var SESSION_SECRET = process.env.SESSION_SECRET || "super secret"

app.use(session({
  cookie: { maxAge: 60000},
  secret: SESSION_SECRET,
  name: 'stocks-app-session',
  resave: true,
  saveUninitialized: true
}));
app.use(flash()) 

Route:

req.flash("danger", "OOPS, Please check your inputs and try again.")

Here with Bootstrap styling:

    <!--
        FLASH MESSAGES
        https://github.com/visionmedia/express-messages#rendering-messages
    -->
    <div class="flash-container">
       <% const messages = getMessages() %>

       <% if (messages) { %>
            <% Object.entries(messages).forEach((obj) => { %>
                <% var category = obj[0] %>
                <% var message = obj[1] %>
                <!--
                    BOOTSTRAP ALERTS
                    https://getbootstrap.com/docs/5.0/components/alerts/#dismissing
                -->
                <div class="alert alert-<%= category %> alert-dismissible fade show" role="alert" style="margin-bottom:0;">
                    <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
                    <%= message %>
                </div>
            <% }) %>
       <% } %>
    </div>
s2t2
  • 2,462
  • 5
  • 37
  • 47