How do I repopulate form fields after validation errors with express-form?

Using node.js and express (2.5.9) with express-form.

How should I repopulate form fields with the submitted values?

I have a get and a post route. If there are validation errors when the form is posted, I redirect the user back to the get, the problem is that the repopulated locals don't show up (I do have autoLocals: true, so I assume it's because I am redirecting and res is reset.)

So how do you guys repopulate and what's your application flow, do you res.send instead of res.redirect and set up the whole thing again? That seems repetitive.

Here's an example of my post route:

app.post(

  '/projects/:id'

  , form(field("title").required("title", "Title is required)
  , function (req, res){

  if (!req.form.isValid){
    res.redirect('/project/'+req.params.id+'/edit');
  }
  else{
    // save to db
  }

});

Not sure if it's best practice, but when I have validation failure, I don't redirect I just re-render the view (often by passing control to the 'get' callback). Somethign like this:

function loadProject(req,res, id){ /* fetch or create logic, storing as req.model or req.project */} 

function editProject(req,res){ /* render logic */ }

function saveProject(req,res){ 
    if(!req.form.isValid){ 
        editProject(req,res);
    }else{
        saveToDb(req.project);
        res.redirect('/project'+req.project.id+'/edit');
    }
}

app.param('id', loadProject);
app.get('/projects/:id/edit', editProject);
app.post('/projects/:id', saveProject);

I had to work on similar problem recently and used two node modules: validator and flashify.

In the form view I configured my form fields as follows:

div.control-group
        label.control-label Description
        div.controls
          textarea(name='eventForm[desc]', id='desc', rows='3').input-xxlarge= eventForm.desc

      div.control-group
        label.control-label Tag
        div.controls
          select(id='tag', name='eventForm[tag]')
            tags = ['Medjugorje', 'Kibeho', 'Lourdes', 'Fatima']
            for tag in tags
              option(selected=eventForm.tag == tag)= tag

Notice the naming convention of the form fields. Then in my config file I set one global variable, which is really just a placeholder for when the form first loads:

//locals
app.locals.eventForm = []; // placeholder for event form repopulation

The validation logic is in my router file and looks like this:

 app.post('/posts', function(req, res){
    var formData = req.body.eventForm;
    var Post = models.events;
    var post = new Post();

    post.text          = formData.desc;
    post.tag           = formData.tag;

    // run validations before saving
    var v = new Validator();
    var isPostValid = true;

    // custom error catcher for validator, which uses flashify
    v.error = function(msg) {
     res.flash('error', msg);
     isPostValid = false;
    }

    v.check(post.text, "Description field cannot be empty").notEmpty();
    v.check(post.tag, "Tag field cannot be empty").notEmpty();

Then I check to see there are errors, and if so, pass the form data back to the view:

  // reject it
  res.render('Event.jade', {page: req.session.page, eventForm: formData});

Notice this evenForm data gets passed back to the view, which repopulates the default values.

The final step is to include the flashify component in your form view.

div(style='margin-top: 60px').container-fluid
      include flashify

The code for the flashify view looks like this:

if (flash.error != undefined)
div.container
    div.alert.alert-error
        b Oops!
        button(type='button', data-dismiss='alert').close ×
        ul
            each error in flash.error
                li= error
if (flash.success != undefined)
div.container
    div.alert.alert-success
        b Success!
        button(type='button', data-dismiss='alert').close ×
        ul
            each success in flash.success
                li= success

I am working with expressjs4.0 to repopulate the forms fields after validation you do:

router.route('/posts/new')
 .get(function(req, res) {
 res.render('posts/new', new Post({}));
});

The second argument in res.render below will set some variables in the view.

res.render('posts/new', new Post({}));

In my view I then set my form fields as follows:

...
<input type="text" name="title" value="<%- post.title %>">
<textarea name="article"><%- post.article %></textarea>
...

When you submit this form, it should be caught by your router like so:

router.route('/posts')
  .post(function(req, res) {
    var post = new Post(req.body)
      post.save(function(err) {
       if (err) {
         res.locals.errors = err.errors;
         res.locals.post = post;
         return res.render('posts/new');
       }
      return res.redirect('/posts');
  });
  ...
})

This line of code, resets the form fields in your view

res.locals.post = post;

I hope someone finds this useful ;)