前回の内容
前回は、商品追加ページの実装をしました↓
https://sakublog.tech/handson/express-app-3/
今回は商品を更新できるようにします。
一覧から更新ページに遷移させる
index.ejsに、各商品にリンクを設置します。
aタグのhrefを書き換えます。
<ul class="products">
<% drinks.forEach((drink)=>{ %>
<li class="product">
<h2 class="product-name">
<a class="product-link" href="/update?id=<%= drink.id %>"
><%= drink.name %></a
>
</h2>
<p class="product-price">¥<%= drink.price %></p>
<p
class="product-temperature <%= drink.temperature ? 'warm' :'cold' %>"
>
<%= drink.temperature ? "あたたかい" :"つめたい" %>
</p>
<button>購入</button>
</li>
<% }) %>
</ul>
これで、クエリパラメータに飲み物のidをつけることができました。
初期値を表示
次に、編集する内容の初期値をフォームに入れます。
- クエリパラメータのidをもとに商品情報を取得
- 商品情報をフォームに渡す
このようなステップで処理を書いていきます。
クエリパラメータのidをもとに商品情報を取得
クエリパラメータは req.query で受け取ることができます
idを受け取れるようにしましょう。
app.get("/update", (req, res) => {
const id = req.query.id;
console.log(id);
res.render("update");
});
にアクセスしてコンソールを見てみます。
idが取得できればOKです🙌
今度はこのidに合致する商品情報を取得しましょう!
app.get("/update", async (req, res) => {
const connection = await mysql.createConnection({
host: process.env.MYSQL_HOST,
database: process.env.MYSQL_DATABASE,
user: process.env.MYSQL_USER,
password: process.env.MYSQL_PASSWORD,
});
const id = req.query.id;
const sql = "SELECT * FROM drinks WHERE id = ?";
const result = await connection.execute(sql, [id]);
console.log(result);
await connection.end();
res.render("update");
});
データベースに接続し、select文で該当idの結果を取得しています。
これで
にアクセスします。
id=2の商品が取得できたらOKです!
商品情報をフォームに渡す
SQLで商品を取得できたら、Expressからejsにデータを渡します。
これは一覧ページと同じ要領でできます。
renderメソッドの第二引数に入れてあげれば良いです。
res.render("update", { drink: result[0][0] });
これでupdate.ejs側に「drink」という変数で結果が渡ってきます。
formを編集します。
<form action="#" method="POST">
<label for="drink-name">商品名:</label>
<input
type="text"
id="drink-name"
name="name"
required
value="<%= drink.name %>"
/>
<label for="drink-price">価格:</label>
<input
type="number"
id="drink-price"
name="price"
required
value="<%= drink.price %>"
/>
<label for="drink-temp">温度:</label>
<select id="drink-temp" name="temp">
<option <%= drink.temperature === 1 ? 'selected' : '' %> value="1">あたたかい</option>
<option <%= drink.temperature === 0 ? 'selected' : '' %> value="0">冷たい</option>
</select>
<button type="submit">更新する</button>
</form>
value属性に初期値を入れると表示されます。
selectタグは、drink.temperatureが1か0かでselected属性を付与しています。
これでフォームに初期値が入るようになりました!
また、更新にはどの商品かが判る必要があるので、idも送信します。
input type=”hidden”
でidを送れるようにしましょう。
<input type="hidden" name="id" value="<%= drink.id %>">
上記をフォームの中に設定すれば準備OKです。
フォームからの値を受け取りバリデーション
追加ページと同様、フォームからのデータをExpress側で受け取れるようにします。
update.ejsのactionを編集します。
<form action="/update" method="POST">
追加と同様に、req.bodyで受け取ることができます。
app.jsにpost時の処理を追加します。
app.post("/update", (req, res) => {
const errors = {
name: [],
price: [],
temp: [],
};
if (req.body.name.length > MAX_NAME_LENGTH) {
errors.name.push("商品名は20文字以内です。");
}
if (req.body.price >= MAX_PRICE || req.body.price <= MIN_PRICE) {
errors.price.push("価格は999円以内で設定できます。");
}
if (req.body.temp !== TEMP_WARM && req.body.temp !== TEMP_COLD) {
errors.temp.push("温度の選択肢が不正です。");
}
if (errors.name.length || errors.price.length || errors.temp.length) {
return res.render("add", { errors: errors });
}
res.redirect("/");
});
追加処理のバリデーション内容をそのままコピーしてきました。
idのバリデーションも追加します。
app.post("/update", (req, res) => {
const errors = {
id: [], // 追記
name: [],
price: [],
temp: [],
};
if (!req.body.id) {
errors.name.push("商品idは必須です。"); // 追記
}
if (req.body.name.length > MAX_NAME_LENGTH) {
errors.name.push("商品名は20文字以内です。");
}
if (req.body.price >= MAX_PRICE || req.body.price <= MIN_PRICE) {
errors.price.push("価格は999円以内で設定できます。");
}
if (req.body.temp !== TEMP_WARM && req.body.temp !== TEMP_COLD) {
errors.temp.push("温度の選択肢が不正です。");
}
if (errors.name.length || errors.price.length || errors.temp.length) {
return res.render("add", { errors: errors });
}
res.redirect("/");
});
追記できたらバリデーションは完成です。
更新処理
SQLのUPDATE文で更新します。
if (errors.name.length || errors.price.length || errors.temp.length) {
return res.render("add", { errors: errors });
}
const connection = await mysql.createConnection({
host: process.env.MYSQL_HOST,
database: process.env.MYSQL_DATABASE,
user: process.env.MYSQL_USER,
password: process.env.MYSQL_PASSWORD,
});
const sql = `UPDATE drinks SET name=?,price=?,temperature=? WHERE id = ?`;
await connection.query(sql, [
req.body.name,
req.body.price,
req.body.temp,
req.body.id,
]);
await connection.end();
res.redirect("/");
INSERTとほとんど同じです。
この状態で画面から更新できるか確かめてみましょう。
id=1のコーヒーを変更してみます。
詳細に遷移し、
次のように変更してみます。
これで更新すると、
更新できました!!!
これで更新処理は完成です。
ここまでお疲れ様でした🙌
次回は削除処理を実装します。