Express - Update
Lesson Objectives
- Create an edit route
- Create a link to the edit route
- Create an update route
- Make the edit page send a PUT request
Edit
| # | Action | URL | HTTP Verb | EJS view filename |
|---|---|---|---|---|
| 1 | Index | /fruits/ | GET | index.ejs |
| 2 | Show | /fruits/:index | GET | show.ejs |
| 3 | New | /fruits/new | GET | new.ejs |
| 4 | Create | /fruits/ | POST | none |
| 5 | Edit | /fruits/:id/edit | GET | edit.ejs |
| 6 | Update | /fruits/:id | PUT | none |
| 7 | Destroy | /fruits/:index | DELETE | none |
Update
Create an update route
In order to UPDATE, we use the http verb PUT.
Inside server.js add the following:
server.js
app.put("/fruits/:index", (req, res) => {
// :index is the index of our fruits array that we want to change
if (req.body.readyToEat === "on") {
//if checked, req.body.readyToEat is set to 'on'
req.body.readyToEat = true;
} else {
//if not checked, req.body.readyToEat is undefined
req.body.readyToEat = false;
}
fruits[req.params.index] = req.body; //in our fruits array, find the index that is specified in the url (:index). Set that element to the value of req.body (the input data)
res.redirect("/fruits"); //redirect to the index page
});
Test with cURL
curl -X PUT -d name="tomato" -d color="red" localhost:3000/fruits/2
curl localhost:3000/fruits
Our last fruit (banana) should now be a tomato
Create an edit route
In our server.js, create a GET route which will just display an edit form for a single fruit
server.js
app.get("/fruits/:index/edit", (req, res) => {
res.render(
"edit.ejs", //render views/edit.ejs
{
//pass in an object that contains
fruit: fruits[req.params.index], //the fruit object
index: req.params.index, //... and its index in the array
}
);
});
Now let's grab our create form and update it for editing in views/edit.ejs
views/edit.ejs
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<h1>Edit Fruit Page</h1>
<form action="/fruits" method="POST">
<label for="name">Name</label>
<input type="text" name="name" id="name" />
<label for="color">Color</label>
<input type="text" name="color" id="color" />
<label for="isReadyToEat">Is Ready to Eat</label>
<input type="checkbox" name="readyToEat" id="isReadyToEat" />
<input type="submit" value="Edit Fruit" />
</form>
</body>
</html>
Create a link to the edit route
Inside our index.ejs file, add a link to our edit route which passes in the index of that item in the url
views/index.ejs
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8" />
<title>Index of Fruits</title>
<link rel="stylesheet" href="main.css" />
</head>
<body>
<h1>Index of Fruits</h1>
<nav>
<a href="/fruits/new">Create a New Fruit</a>
</nav>
<ul>
<% fruits.forEach((fruit, index) => { %>
<li>
<a href="/fruits/<%=index%>"> <%= fruit.name %></a>
<form action="/fruits/<%= index %>?_method=DELETE" method="POST">
<input type="submit" value="DELETE" />
</form>
<a href="/fruits/<%=index %>/edit">Edit</a>
</li>
<% }) %>
</ul>
</body>
</html>
Make the edit page send a PUT request
When we click "Submit Changes" on our edit page (edit.ejs), the form needs to make a PUT request to our update route
views/edit.ejs
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Edit a Fruit</title>
</head>
<body>
<h1>Edit Fruit Page</h1>
<form action="/fruits/<%=index%>?_method=PUT" method="POST">
<label for="name">Name</label>
<input type="text" name="name" id="name" />
<label for="color">Color</label>
<input type="text" name="color" id="color" />
<label for="isReadyToEat">Is Ready to Eat</label>
<input type="checkbox" name="readyToEat" id="isReadyToEat" />
<input type="submit" value="Edit Fruit" />
</form>
</body>
</html>
What is frustrating, is that our users have to remember which fruit they clicked on and update/reenter all the values.
We should at least set values in the form for the user to update
views/edit.ejs
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Edit a Fruit</title>
</head>
<body>
<h1>Edit Fruit Page</h1>
<form action="/fruits/<%=index%>?_method=PUT" method="POST">
<label for="name">Name</label>
<input type="text" name="name" id="name" value="<%=fruit.name%>" />
<label for="color">Color</label>
<input type="text" name="color" id="color" value="<%=fruit.color%>" />
<label for="isReadyToEat">Is Ready to Eat</label>
<input type="checkbox" name="readyToEat" id="isReadyToEat"
<% if(fruit.readyToEat === true){ %>
checked
<% } %> />
<input type="submit" value="Edit Fruit" />
</form>
</body>
</html>