Forms and redirect after POST
A form is the main way to get data from a visitor. In Express it takes two routes: GET shows an empty form, POST receives the filled-in one, saves the data and redirects the visitor to another page.
Routes
Add two addresses to src/routes/posts.js. The /new route must come before /:id, otherwise the word new would be taken as a post number:
// src/routes/posts.js
router.get('/', postsController.index);
router.get('/new', postsController.create);
router.post('/', postsController.store);
router.get('/:id', postsController.show);And remember that express.urlencoded() must already be enabled in src/app.js — without it req.body is empty.
The form template
Create views/posts/new.ejs:
<%- include('../partials/header') %>
<h1>New post</h1>
<form method="post" action="/posts">
<label>
Title
<input name="title">
</label>
<label>
Text
<textarea name="body" rows="8"></textarea>
</label>
<button>Publish</button>
</form>
<%- include('../partials/footer') %>A field's name attribute becomes a key in req.body: the value of the title field arrives in req.body.title.
Handlers
// src/controllers/postsController.js
export function create(req, res) {
res.render('posts/new', { title: 'New post' });
}
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}`);
}Open /posts/new, fill in the fields and press "Publish". The browser goes to the new post's page, and in the /posts list it appears last.
A link to the form
Add a link to views/posts/index.ejs so the form can be reached from the list:
<a href="/posts/new">Write a post</a>Why redirect
You could answer with the post template right away via res.render(). But then the address bar would keep the POST request address, and on refresh the browser would submit the form again — the post would be created twice. A redirect turns the response into an ordinary GET request that can be refreshed as often as you like. This technique is called Post/Redirect/Get.
| Step | Request | Response |
|---|---|---|
| 1 | GET /posts/new | Page with the form |
| 2 | POST /posts | Redirect to /posts/3 |
| 3 | GET /posts/3 | The new post's page |
Common mistake
A form without method="post" sends data with GET — it ends up in the address bar and in req.query, and the router.post() route does not fire. Check that the form has method="post" and that the address in action matches the route address.