Search code examples
ajaxnode.jsexpresspugconnect-flash

Jade html not updated after a redirect in Express.js


I'm currently having some trouble displaying a flash message in Express.js using Jade's templating engine and connect-flash. I am simply trying to flash an error message when the user tries to add a new User object to my database that already exists. However the flash message is not showing up on my page after calling router.post and redirecting back to the index (code below).

Through various console.logs and debugging, I have found that the data I am posting is indeed posting correctly, and the flash message is being set. What I have found is that on the redirect, all of the correct data is passing to the Jade template, but the variables are not being updated in the file itself. I am now wondering if this is a session related issue, or just something Flash/Jade/Express related that I am completely overlooking?

In the code below I am logging session data as well as setting the flash message to a variable. If the array for the flash message(s) is empty (i.e. on page load), an array is set with a message that says so. If the flash message(s) array contains a flash message, the test array is set with a message that says so.

index.js:

router.get('/', function(req, res, next) {
    console.log(req.session);
    var testArray;
    var errorMessages = req.flash('user-error');
    if (errorMessages.length === 0)
        testArray = ['errorMessages is empty'];
    else
        testArray = ['errorMessages contains a message now'];
    console.log(errorMessages);
    console.log(testArray);
    res.render('index', { 
        message: errorMessages,
        tester: testArray, 
        ...other irrelevant vars being passed...
    });
});

router.post('/add', function(req, res, next) {
    var ajaxData = req.body;
    console.log(ajaxData);

    User.findOne({name: ajaxData.name}, function(err, user) {
        if (err) return console.error(err);
        // if User DNE already in DB
        if (user === null) {
            ...new user created and saved here...
        }
        /*where the important stuff begins*/
        else {
            console.log("flash message set");
            req.flash('user-error', "A user with that name already exists!");
        }
        // redirect to index
        res.redirect('/');
    });
});

In my Jade template, I'm again logging errorMessages and testArray to make sure everything is passed to the file correctly (it is) then showing the variables.

index.jade

-console.log(message);
-console.log(tester);
.error-box Error: #{message}
.error-box Error: #{tester}

Initially loading the page, I will get the following HTML output:

<div class="error-box">Error: </div>
<div class="error-box">Error: errorMessages is empty</div>

No surprises here. But when I submit the form with data that sets the error flash message, I get the updated logs from router.get('/') and index.jade with both the correct errorMessages and testArray variables. However my HTML output remains the same:

<div class="error-box">Error: </div>
<div class="error-box">Error: errorMessages is empty</div>

Clearly the variables being passed to Jade are being updated correctly, but it appears that Jade is simply not updating the HTML. With my somewhat limited knowledge of how connect-flash and Jade work, this would lead me to believe that this is a session related issue, however my code in app.js appears to be setup correctly...

var session = require('express-session');
var flash = require('connect-flash');
app.use(session({
  secret: 'secret',
  cookie: { maxAge: 60000 },
  resave: false,
  saveUninitialized: false
}));
app.use(flash());

I am relatively new to Express.js, so I feel like there might be something small I am overlooking or don't understand, but I've tried to be as detailed as possible so I'm hoping someone can help me out here!


Solution

  • After more careful inspection, I found that what was really causing the issue was that res.redirect('/') was not running, as I was attempting to use AJAX on the client side to call router.post('/add').

    I solved this by simply removing my AJAX request, then going back into my HTML and changing my form's attributes (the form whose data I was sending via AJAX) to include method="POST" and action="/add". This is the proper way to make a SERVER SIDE call to my router.post('/add').

    I found that someone was having the same problem here, and this question initially led me to look into the AJAX/Client Side vs. Server Side issue. I found the latter question in a comment from @herbyme on this post.