駆け出しのエンジニア日記

プログラミング言語勉強中の奮闘日記

ExpressでMongooseを使う part5

農産物の商品管理アプリ作成の続きです。

今回は、商品の編集・更新ができるようにしていきます。

ルーティングを追加していきます。

・index.js

const express = require('express');
const app = express();
const path = require('path');
const mongoose = require('mongoose');
//method-overrideの宣言
const methodOverride = require('method-override');
const Product = require('./models/product');
mongoose.connect('mongodb://localhost:27017/farmStand',
{ useNewUrlParser: true, useUnifiedTopology: true })
.then*1;
app.set('view engine', 'ejs');
app.use(express.urlencoded({ extended: true }));
//リクエストはpostかgetのみなのでPUT, DELETEを使えるようにオーバーライドしておく
app.use(methodOverride('_method'))
//カテゴリを配列にしておき、ejsの方でループさせることで管理
const categories = ['果物', '野菜', '乳製品'];
//商品一覧
app.get('/products', async (req, res) => {
const products = await Product.find({})
res.render('products/index', { products});
})
//商品登録フォーム
app.get('/products/new', (req, res) => {
res.render('products/new', { categories });
})
//リクエス送信先
app.post('/products', async (req, res) => {
const newProduct = new Product(req.body);
await newProduct.save();
res.redirect(`/products/${newProduct._id}`);
})
//商品詳細ページ
app.get('/products/:id', async (req, res) => {
//id取得
const { id } = req.params;
const product = await Product.findById(id).populate('farm', 'name');
res.render('products/show', { product });
})

//商品の更新
app.get('/products/:id/edit', async (req, res) => {
//id取得
const { id } = req.params;
const product = await Product.findById(id);
res.render('products/edit', { product, categories });
})
 
//編集のリクエストエンドポイント
app.put('/products/:id', async (req, res) => {
const { id } = req.params;
//findByIdAndUpdateは更新前のものが渡されるので、new: trueで更新後を取得する
const product = await Product.findByIdAndUpdate(id, req.body,
 { runValidators: true, new: true });
res.redirect(`/products/${product._id}`);
})
 
app.listen(3000, () => {
console.log('ポート3000で待機');
})

※編集のリクエストのエンドポイントのルーティングを記述する際の注意点です。

フォームのリクエストは「GET」か「POST」しか投げることができません。

そこで使用するのが、「method-override」です。これを使うことで「GET」か

「POST」以外のリクエストもフォームから投げれるようになります。

また「findByIdAndUpdate( )」の第三引数にも、「 runValidators 」をtrueにするこ

とで更新の際にバリデーションが走るように設定もしておきます。

 

次は編集画面のテンプレートを作成します。

・edit.ejs

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>商品の編集</title>
</head>
<body>
<h1>商品の編集</h1>
<form action="/products/<%= product._id %>?_method=PUT" method="POST">
<label for="name">商品名</label>
<input type="text" name="name" id="name" placeholder="商品名"
value="<%= product.name %>">
<label for="price">価格</label>
<input type="number" name="price" id="price" placeholder="価格"
value="<%= product.price %>">
<label for="category">カテゴリ</label>
<select name="category" id="category">
<% for(let category of categories) {%>
<option value="<%= category %>" <%=product.category===category ? 'selected' :''%>>
<%= category %>
</option>
<% } %>>
</select>
<button>登録</button>
</form>
<a href="/products/<%= product._id %>"> キャンセル</a>
</body>
</html>

ここまで記述できれば実際の画面で確認してみます

編集フォームへ遷移します。登録ボタンを押下

無事に商品の更新がされています。

*1:) => {

console.log('MongoDBコネクションOK!!');
})
.catch(err => {
console.log('MongoDBコネクションエラー!!!');
console.log(err);
});
app.set('views', path.join(__dirname, 'views'