Express.jsforms处理和错误检查 – 正确的方法

我有一个模板,我呈现GET请求中的表单:

 app.get('/register', function (req, res) { res.render('register', { title: 'Register' , twitterDetails: req.session.twitterDetails } ); }); 

然后我在POST请求中处理表单:

 app.post('/register', function (req, res, next) { // Generic validation req.assert('name', 'Name is empty').notEmpty(); req.assert('username', 'Username is empty').notEmpty(); // Email validation req.assert('email', 'Email is invalid.').isEmail(); req.assert('email', 'Email field is empty').notEmpty(); // Password validation req.assert('password', 'Password too short. Must be 6 characters or more.').len(6); req.assert('password', 'Passwords do not match.').is(req.body.confirmPassword); req.assert('password', 'Password field is empty').notEmpty(); req.assert('confirmPassword', 'Confirm password field is empty').notEmpty(); var errors = req.validationErrors(true); if (errors) { console.log(errors); // What do to if there are errors? } // If there are no errors, continue handling the form… }); 

在这个表单处理程序中,我正在用express-validator模块检查错误。 这很好,但我的问题是如果有错误该怎么办。 AFAIK有两种select:

  1. 将用户redirect到/register ,使用req.flash将错误传递给下一个请求
  2. 重新渲染模板并将错误直接传递给模板

有了第一个选项,我可能会将用户从POST解脱出来,从而失去表单数据的风险。 我也可以使用req.flash来填充表单中的数据,但是在刷新页面时会消失。

有了第二个选项,我正在重复自己 – 特别是如果我发送了很多variables到模板中,这将不得不重复。 我还需要通过模板传递所有的表单数据,并用这些值填写表单。

处理这样的表单的正确程序是什么?

使用选项1.这被称为POST /redirect/ GET模式,并在任何地方使用。

如果您害怕丢失数据,请使用会话。 这就是他们的目的。 在会议期间保持状态。

不要忘记HTTP是无状态的。

我认为你应该使用选项2。

POST /redirect/ GET模式主要适用于用户成功的提交,并有助于避免重复的post。 这并不意味着你应该把它用于失败的提交

对于失败的提交,通常的做法是不redirect到另一个页面,而只是用错误消息重新呈现表单。

选项1确实提高了可用性,因为用户在提交失败后刷新页面时不会重新提交。 另一方面,处理它要复杂得多,因为它需要将表单数据存储在会话或GET参数中。

总的来说:虽然scheme1在可用性方面可能是最好的,但scheme2仍然是普遍的做法和更实际的方式。

另请参阅: 在Post / Redirect / Get模式中如何处理服务器端错误?

下面是一个例子:

我将它添加到我的./views/layout.ejs页面底部的标记中:

 <script> var app = window.app || {}; app.req = app.req || {}; app.req.err = <%- JSON.stringify(err) %>; app.req.q = <%- JSON.stringify(q) %>; </script> 

来自POST错误的实际数据示例:

 app.req.err = {"email":{"param":"email","msg":"Enter email","value":""}}; app.req.q = {"username":"chovy","email":"","password":"somepassword"}; 

我有每个POST这样做的中间件:

  res.locals.q = req.body; res.locals.err = false; 

如果遇到错误,则填充它:./routes/signup.js:

  req.assert('email', 'Enter email').notEmpty().isEmail(); req.assert('username', 'Enter username').notEmpty().isAlphanumeric().len(3,20); req.assert('password', 'Enter password').notEmpty().notContains(' ').len(5,20); res.locals.err = req.validationErrors(true); 

然后,我的全球客户端js在每个页面加载运行这个例程,基本上检查app.req.err并处理表单错误:

 app.utils.form.errors(); 

这是function:

 app.utils.form.errors = function(err){ err = err || app.req.err; app.utils.form.prefill(); for ( var e in err ) { var $field = $('[name='+e+']'), $el = $field.parents('p'); $el.addClass('err'); $el.append('<span class="msg">'+err[e].msg+'</span>'); } }; 

从app.req.q预填表单:

 app.utils.form.prefill = function(){ for ( var param in app.req.q ) { var $field = $('[name='+param+']'); $field.val(app.req.q[param]); } }; 

你可以看到它的行动,如果你去这个registry单,只是提交空白,然后查看源代码: http : //wishd.me/signup JavaScript是在http://wishd.me/app.js

诀窍是留下足够的空间,以便您的表单域中的内联错误消息,因为所有错误将被处理相同,无论它在哪个字段上。 当然,我对css有一些例外,可能会重新定位内联错误消息,为红色标签着色等。

http://wishd.me/style.css寻&#x627E;.err类

我正在使用expressjs4.0在validation后重新填充表单字段:

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

下面res.render中的第二个参数将在视图中设置一些variables。

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

在我看来,我然后设置我的表单域如下:

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

当你提交这个表单时,它应该像你这样被路由器抓住:

 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'); }); ... }) 

这行代码重置视图中的表单字段

 res.locals.post = post; 

我希望有人认为这有用;)