👉 C admin.js
...
exports.getEditProduct = (req, res, next) => {
const editMode = req.query.edit;
if (!editMode) {
return res.redirect('/');
}
const prodId = req.params.productId;
Product.findById(prodId, product => {
if (!product) {
return res.redirect('/');
}
res.render('admin/edit-product', {
pageTitle: 'Edit Product',
path: '/admin/edit-product',
editing: editMode,
product: product
});
});
};
...
🧐 쿼리 매개 변수
- 쿼리 매개 변수는 ?를 추가하여 모든 URL에 추가할 수 있으며 edit=true를 비롯한 =표시로 분할한 키 값 쌍을 넣어주면 된다.
- & 표시로 분할해 줌으로써 다수의 쿼리 매개 변수를 입력할 수도 있고 이것은 부차적 데이터라고 한다. ex) title=new
- 라우트는 ? 표시까지의 부분을 통해 결정된다. 따라서 routes 파일로 전달할 쿼리 매개 변수에 대한
정보는 추가할 필요가 없다.
- 위 코드는 editMode가 true일 때. prodId를 찾고 admin/edit-product를 render한다.
👉 V edit-product.ejs
...
<body>
<%- include('../includes/navigation.ejs') %>
<main>
<form class="product-form" action="/admin/<% if (editing) { %>edit-product<% } else { %>add-product<% } %>" method="POST">
<div class="form-control">
<label for="title">Title</label>
<input type="text" name="title" id="title" value="<% if (editing) { %><%= product.title %><% } %>">
</div>
<div class="form-control">
<label for="imageUrl">Image URL</label>
<input type="text" name="imageUrl" id="imageUrl" value="<% if (editing) { %><%= product.imageUrl %><% } %>">
</div>
<div class="form-control">
<label for="price">Price</label>
<input type="number" name="price" id="price" step="0.01" value="<% if (editing) { %><%= product.price %><% } %>">
</div>
<div class="form-control">
<label for="description">Description</label>
<textarea name="description" id="description" rows="5"><% if (editing) { %><%= product.description %><% } %></textarea>
</div>
<% if (editing) { %>
<input type="hidden" value="<%= product.id %>" name="productId">
<% } %>
<button class="btn" type="submit"><% if (editing) { %>Update Product<% } else { %>Add Product<% } %></button>
</form>
</main>
<%- include('../includes/end.ejs') %>
🧐 쿼리 매개 변수
👉 M Product.js
module.exports = class Product {
constructor(id, title, imageUrl, description, price) {
this.id = id;
this.title = title;
this.imageUrl = imageUrl;
this.description = description;
this.price = price;
}
save() {
getProductsFromFile(products => {
if (this.id) {
const existingProductIndex = products.findIndex(
prod => prod.id === this.id
);
const updatedProducts = [...products];
updatedProducts[existingProductIndex] = this;
fs.writeFile(p, JSON.stringify(updatedProducts), err => {
console.log(err);
});
} else {
this.id = Math.random().toString();
products.push(this);
fs.writeFile(p, JSON.stringify(products), err => {
console.log(err);
});
}
});
}
🧐 제품 id 확인
- ID가 이미 있는지를 확인하고, 새 제품을 생성할 때 ID도 받아오도록 해준다.
- this.id=id로 설정해 주고 새 제품의 경우 null을 전달하여 아직 ID가 없는 제품들도 생성할 수 있도록 한다.
...
exports.postAddProduct = (req, res, next) => {
const title = req.body.title;
const imageUrl = req.body.imageUrl;
const price = req.body.price;
const description = req.body.description;
const product = new Product(null, title, imageUrl, description, price);
product.save();
res.redirect('/');
};
...
exports.postEditProduct = (req, res, next) => {
const prodId = req.body.productId;
const updatedTitle = req.body.title;
const updatedPrice = req.body.price;
const updatedImageUrl = req.body.imageUrl;
const updatedDesc = req.body.description;
const updatedProduct = new Product(
prodId,
updatedTitle,
updatedImageUrl,
updatedDesc,
updatedPrice
);
updatedProduct.save();
res.redirect('/admin/products');
};
...
🧐 AddProduct, EditProduct
- postAddProduct Controller는 새 제품의 경우 null을 전달하여 아직 ID가 없는 제품들도 생성할 수 있도록 했다.
- postEditProduct Controller는 Product class로 값을 넘겨서 Eidt될때 this가 이 값을 사용한다.