创建作者表单
本子文章展示了如何定义一个用于创建 `Author` 对象的页面。
导入验证和清理方法
与 类型表单 一样,要使用 `express-validator`,我们必须 `require` 我们想要使用的函数。
打开 ** /controllers/authorController.js **,在文件顶部(路由函数上方)添加以下行
const { body, validationResult } = require("express-validator");
控制器 - 获取路由
找到导出的 `author_create_get()` 控制器方法,并将其替换为以下代码。这将呈现 ** author_form.pug ** 视图,并传递 `title` 变量。
// Display Author create form on GET.
exports.author_create_get = (req, res, next) => {
res.render("author_form", { title: "Create Author" });
};
控制器 - 发送路由
找到导出的 `author_create_post()` 控制器方法,并将其替换为以下代码。
// Handle Author create on POST.
exports.author_create_post = [
// Validate and sanitize fields.
body("first_name")
.trim()
.isLength({ min: 1 })
.escape()
.withMessage("First name must be specified.")
.isAlphanumeric()
.withMessage("First name has non-alphanumeric characters."),
body("family_name")
.trim()
.isLength({ min: 1 })
.escape()
.withMessage("Family name must be specified.")
.isAlphanumeric()
.withMessage("Family name has non-alphanumeric characters."),
body("date_of_birth", "Invalid date of birth")
.optional({ values: "falsy" })
.isISO8601()
.toDate(),
body("date_of_death", "Invalid date of death")
.optional({ values: "falsy" })
.isISO8601()
.toDate(),
// Process request after validation and sanitization.
asyncHandler(async (req, res, next) => {
// Extract the validation errors from a request.
const errors = validationResult(req);
// Create Author object with escaped and trimmed data
const author = new Author({
first_name: req.body.first_name,
family_name: req.body.family_name,
date_of_birth: req.body.date_of_birth,
date_of_death: req.body.date_of_death,
});
if (!errors.isEmpty()) {
// There are errors. Render form again with sanitized values/errors messages.
res.render("author_form", {
title: "Create Author",
author: author,
errors: errors.array(),
});
return;
} else {
// Data from form is valid.
// Save author.
await author.save();
// Redirect to new author record.
res.redirect(author.url);
}
}),
];
**警告:** 永远不要使用 `isAlphanumeric()` 验证 *姓名*(如上所示),因为许多姓名使用其他字符集。我们在这里这样做是为了演示如何使用验证器,以及如何将其与其他验证器和错误报告链接。
此代码的结构和行为几乎与创建 `Genre` 对象完全相同。首先,我们验证和清理数据。如果数据无效,我们将重新显示表单,以及用户最初输入的数据和错误消息列表。如果数据有效,我们将保存新的作者记录,并将用户重定向到作者详细信息页面。
与 `Genre` 后处理程序不同,我们在保存之前不会检查 `Author` 对象是否已存在。可以说我们应该这样做,但就目前而言,我们可以拥有多个具有相同名称的作者。
验证代码演示了一些新功能
- 我们可以使用 `withMessage()` 指定如果前一个验证方法失败要显示的错误消息,将验证器链接在一起。这使得在没有大量代码重复的情况下提供特定错误消息变得非常容易。js
[ // Validate and sanitize fields. body("first_name") .trim() .isLength({ min: 1 }) .escape() .withMessage("First name must be specified.") .isAlphanumeric() .withMessage("First name has non-alphanumeric characters."), // … ];
- 我们可以使用 `optional()` 函数仅在输入字段后运行后续验证(这允许我们验证可选字段)。例如,下面我们检查可选的出生日期是否为符合 ISO8601 的日期(传递的 `{ values: "falsy" }` 对象意味着我们将接受空字符串或 `null` 作为空值)。js
[ body("date_of_birth", "Invalid date of birth") .optional({ values: "falsy" }) .isISO8601() .toDate(), ];
- 参数作为字符串从请求中接收。我们可以使用 `toDate()`(或 `toBoolean()`)将它们转换为适当的 JavaScript 类型(如上面验证器链的末尾所示)。
视图
创建 ** /views/author_form.pug ** 并复制以下文本。
extends layout
block content
h1=title
form(method='POST')
div.form-group
label(for='first_name') First Name:
input#first_name.form-control(type='text', placeholder='First name (Christian)' name='first_name' required value=(undefined===author ? '' : author.first_name) )
label(for='family_name') Family Name:
input#family_name.form-control(type='text', placeholder='Family name (Surname)' name='family_name' required value=(undefined===author ? '' : author.family_name))
div.form-group
label(for='date_of_birth') Date of birth:
input#date_of_birth.form-control(type='date' name='date_of_birth' value=(undefined===author ? '' : author.date_of_birth) )
button.btn.btn-primary(type='submit') Submit
if errors
ul
for error in errors
li!= error.msg
此视图的结构和行为与 ** genre_form.pug ** 模板完全相同,因此我们不再赘述。
**注意:** 一些浏览器不支持 `type="date"` 的输入,因此您将无法获得日期选择器小部件或默认的 `dd/mm/yyyy` 占位符,而是会获得一个空的纯文本字段。一个解决方法是显式添加 `placeholder='dd/mm/yyyy'` 属性,这样在功能较弱的浏览器上,您仍然会收到有关所需文本格式的信息。
挑战:添加死亡日期
上面的模板缺少用于输入 `date_of_death` 的字段。按照与出生日期表单组相同的模式创建该字段!
它看起来像什么?
运行应用程序,在浏览器中打开 `https://127.0.0.1:3000/`,然后选择 *创建新作者* 链接。如果一切设置正确,您的网站应该看起来像以下屏幕截图。输入值后,它将被保存,您将被带到作者详细信息页面。
**注意:** 如果您尝试使用各种日期输入格式,您可能会发现 `yyyy-mm-dd` 格式行为不端。这是因为 JavaScript 将日期字符串视为包含 0 小时的时
下一步
- 返回 Express 教程第 6 部分:使用表单。
- 继续进行第 6 部分的下一篇文章:创建书籍表单。