0

I just started a new nodejs app, which will contain a notable amount of forms for creating and editing/updating database values. My question is: How can I repopulate form entries if the given data is invalid?

Example: Somebody tries to login. If the credentials are wrong I'm using something like the following to display the login page again:

res.render('sessions/new')

Thing is, the username is not populated with the request data. I was wondering how to accomplish this both easy and clean. Since there is no form_for like in rails, I guess I have to implement that manually, right? My first approach was to bypass the request body/params as locals to the render function and set the value within my jade template like so:

// In controller/route
res.render('sessions/new', req.body)

// In template
input(type='text', name='username', value=locals.username)

Is there a better or more unobtrusive solution? I mean the example above works and is pretty easy to implement, just wondering if I missed something. This is also interesting for stuff like adding an error class to invalid form fields. Couldn't really find anything on the web.

Thanks in advance!

Daniel Torres
  • 749
  • 1
  • 7
  • 17

2 Answers2

3

I use connect-flash middleware. Typically this module is intended for informative messages (success, error etc) but it also works well for persisting form data across requests.

When the form data is POSTed:

router.post('/create-user', function(res, req, next) {
  // Do stuff
  if (invalid) {
    req.flash('form', req.body);
    res.redirect('/create-user');
  }
});

Then on the GET side:

router.get('/create-user', function(res, req, next) {
  // Render the template with form data
  res.render('my_template', {
    form: req.flash('form')[0] || null
  });
});

Then in my_template.hbs (I use Handlebars):

<form>
  <input type="email" name="email" value="{{form.email}}">
  <input type="name" name="name" value="{{form.name}}">
  ...
</form>

Hope that helps.

Richard Francis
  • 441
  • 3
  • 5
1

I do it on client side with jQuery.

I use express-validator to generate an error map, this contains field name, original value, and an error message.

Then I just print that inside script tags on my layout template at the bottom of the page, and in jQuery I check if it's empty or not and loop through the error stack. Tagging the field as error and displaying original value and error message.

Here is express-validator code:

route:

  req.assert('username', 'Enter username').notEmpty();
  req.assert('password', 'Enter password').notEmpty();
  res.locals.errors = req.validationErrors(true);
  res.render('/login');

view:

<p>
 <label>Username</label>
 <input name="username" />
</p>

<script>var errors = <%= errors %>;</script>

Client side javascript (jQuery):

    for ( var e in errors ) {
        var $field = $('[name='+e+']'),
        $el = $field.parents('p');

        $el.addClass('err');
        $el.append('<span class="msg">'+errors[e].msg+'</span>');
    }

The alternative is to do a bunch of if/else and echo statements in your view which can get real ugly, real quick.

chovy
  • 72,281
  • 52
  • 227
  • 295
  • Hm, since I'm validating my data within models, express-validate doesn't really make sense for me, but thanks for the hint. – Daniel Torres Oct 18 '12 at 10:03