Формы и перенаправление после POST
Форма — основной способ получить данные от посетителя. Работа с ней в Express состоит из двух маршрутов: GET показывает пустую форму, POST принимает заполненную, сохраняет данные и перенаправляет посетителя на другую страницу.
Маршруты
Добавьте в src/routes/posts.js два адреса. Маршрут /new должен стоять выше /:id, иначе слово new будет принято за номер статьи:
// src/routes/posts.js
router.get('/', postsController.index);
router.get('/new', postsController.create);
router.post('/', postsController.store);
router.get('/:id', postsController.show);И не забудьте, что в src/app.js уже должна быть подключена express.urlencoded() — без неё req.body будет пустым.
Шаблон формы
Создайте views/posts/new.ejs:
<%- include('../partials/header') %>
<h1>Новая статья</h1>
<form method="post" action="/posts">
<label>
Заголовок
<input name="title">
</label>
<label>
Текст
<textarea name="body" rows="8"></textarea>
</label>
<button>Опубликовать</button>
</form>
<%- include('../partials/footer') %>Атрибут name у поля становится ключом в req.body: значение поля title придёт в req.body.title.
Обработчики
// src/controllers/postsController.js
export function create(req, res) {
res.render('posts/new', { title: 'Новая статья' });
}
export function store(req, res) {
const post = {
id: posts.length + 1,
title: req.body.title,
body: req.body.body,
};
posts.push(post);
res.redirect(`/posts/${post.id}`);
}Откройте /posts/new, заполните поля и нажмите «Опубликовать». Браузер перейдёт на страницу новой статьи, а в списке /posts она появится последней.
Ссылка на форму
Добавьте ссылку в views/posts/index.ejs, чтобы до формы можно было дойти со списка:
<a href="/posts/new">Написать статью</a>Зачем перенаправлять
Можно было бы сразу ответить шаблоном статьи через res.render(). Но тогда в адресной строке остался бы адрес POST-запроса, и при обновлении страницы браузер отправил бы форму ещё раз — статья создалась бы дважды. Перенаправление превращает ответ в обычный GET-запрос, который можно обновлять сколько угодно. Этот приём называют Post/Redirect/Get.
| Шаг | Запрос | Ответ |
|---|---|---|
| 1 | GET /posts/new | Страница с формой |
| 2 | POST /posts | Перенаправление на /posts/3 |
| 3 | GET /posts/3 | Страница новой статьи |
Частая ошибка
Форма без method="post" отправляет данные методом GET — они окажутся в адресной строке и в req.query, а маршрут router.post() не сработает. Проверьте, что у формы указан method="post", а адрес в action совпадает с адресом маршрута.