'How to iterate over an array with map or forEach in node express with the HBS template engine and return it in my .hbs file?
[when iterating over objects I have no problem, but I have no way or idea of how to do it with the arrays, I need that after filling in the data of my form when clicking on send, it takes me to my page with the route /products (which until now that works) but I need it to show me a list of all the products that I am adding, and it only shows me a list with a single product, I keep adding products and it replaces the singular product that was there before, therefore I cannot keep all the products]
[INDEX.JS]
const express = require("express");
const routes = require("./routes");
const path = require("path");
let hbs = require('hbs')
const app = express();
const port = 8080;
const { customAlphabet } = require("nanoid");
const nanoid = customAlphabet("1234567890", 5);
hbs.localsAsTemplateData(app);
app.set("view engine", "hbs");
app.use(express.static(__dirname + "public"));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.get("/", (req, res) => {
res.render("form", {
title: "Productos",
});
});
// app.locals.titulo = "Mi tienda";
app.post("/productos", (req, res) => {
if (!req.body.title && !req.body.price && !req.body.thumbnail) {
res.status(400).json({
error: "Bad Request",
message: "Title, price and thumbnail are required",
});
}
const body = req.body;
const producto = [
{
id: Number(nanoid(5)),
title: body.title,
price: body.price,
thumbnail: body.thumbnail,
},
];
console.log(producto);
return res.render("productos", {
producto,
});
});
app.get("/productos", (req, res) => {
res.render("form", {
title: "Productos",
});
});
routes(app);
app
.listen(port, () => {
console.log(`App listening on port ${port}!`);
})
.on("error", (err) => {
console.log(err);
throw err;
});
[FORM.JS]
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=10" />
<title>Api Shoes Rest</title>
<style>
input::-webkit-outer-spin-button, input::-webkit-inner-spin-button {
-webkit-appearance: none; margin: 0; } input[type=number] {
-moz-appearance: textfield; }
</style>
</head>
<body>
<h1 style="font-family: arial; text-align: center">Ingresá tu producto!</h1>
<form
action="/productos"
method="POST"
style="
display: flex;
flex-direction: column;
text-align: center;
font-size: 21px;
font-weight: bold;
font-family: Arial, Helvetica, sans-serif;
align-items: center;
justify-content: center;
margin: 5px 0;
"
>
<label for="title">
<input
type="text"
name="title"
id="title"
placeholder="Title"
style="
margin-bottom: 10px;
border: 1px solid #ccc;
outline: none;
border-radius: 5px;
padding: 8px;
"
required
/>
</label>
<label for="price">
<input
placeholder="Price"
name="price"
id="price"
style="
margin-top: 10px;
margin-bottom: 10px;
border: 1px solid #ccc;
outline: none;
border-radius: 5px;
padding: 8px;
"
pattern="[0-9.]+"
type="number"
required
/>
</label>
<label for="thumbnail">
<input
type="url"
pattern="https?://.+"
title="Include http://"
placeholder="Thumbnail(URL)"
name="thumbnail"
id="thumbnail"
style="
margin-top: 10px;
margin-bottom: 10px;
border: 1px solid #ccc;
outline: none;
border-radius: 5px;
padding: 8px;
"
required
/>
</label>
<button
style="
padding: 8px 70px;
font-weight: 700;
text-align: center;
font-size: 15px;
letter-spacing: 1px;
max-width: 200px;
cursor: pointer;
font-family: Helvetica, sans-serif;
border: 1px solid #ccc;
border-radius: 5px;
background-color: #ccc;
margin-top: 10px;
text-transform: uppercase;
"
type="submit"
>
SEND
</button>
</form>
<script>
document.querySelector("form").addEventListener("input", function (e) {
const tgt = e.target; if (tgt.type && tgt.type === "number") { const val =
tgt.value; const nums = val.replace(/[^\d.-]/g, ""); if (!/\d+/.test(val))
tgt.value = ""; } });
</script>
</body>
</html>
[PRODUCTOS.HBS]
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css
"
/>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Productos</title>
</head>
<body class="container form-control-plaintext">
<div class="container">
<div class="row">
<div class="col-12">
<h1>Productos</h1>
</div>
</div>
<table class="table">
<thead class="table-dark">
<tr>
<th class="text-center" scope="col">#</th>
<th class="text-center" scope="col">Product</th>
<th class="text-center" scope="col">Price</th>
<th class="text-center" scope="col">Preview</th>
</tr>
</thead>
<tbody>
{{#each producto}}
<tr>
<th class="text-center" scope="row">{{id}}</th>
<td class="text-center">{{title}}</td>
<td class="text-center">{{price}}</td>
<td class="text-center">
<img
src={{thumbnail}}
alt="535353"
style="width:100%; height: 184px; margin-left: 9px;"
/>
</td>
</tr>
{{/each }}
</tbody>
</table>
<button style="outline: none; height: 55px; text-align: center; float: left; font-weight: bold; font-size: 26px; border: none; background-color: rgb(0, 0, 0); color: rgb(255, 255, 255);">
Go to home
</button>
<script
src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"
></script>
</body>
</html>
[API.JS]
const { customAlphabet } = require("nanoid");
const nanoid = customAlphabet("1234567890", 5);
class Productos {
constructor() {
this.productos = [];
}
obtenerProductos() {
return this.productos;
}
obtenerProducto(id) {
return this.productos.find((producto) => producto.id === Number(id));
}
create(data) {
const newProduct = {
...data,
id: Number(nanoid(5)),
};
this.productos.push(newProduct);
return newProduct;
}
eliminarProducto(id) {
this.productos = this.productos.filter(
(producto) => producto.id !== Number(id)
);
}
actualizarProducto(id, data) {
const producto = this.obtenerProducto(id);
if (producto) {
Object.assign(producto, data);
return producto;
}
throw new Error();
}
}
module.exports = Productos;
[PRODUCTSROUTER.JS]
const express = require("express");
const Productos = require("../api");
const router = express.Router();
const itemService = new Productos();
router.get("/", (req, res) => {
res.render("form", {
title: "Productos",
})
});
router.post("/", (req, res) => {
if (!req.body.title && !req.body.price && !req.body.thumbnail) {
res.status(400).json({
error: "Bad Request",
message: "Title, price and thumbnail are required",
});
}
const producto = itemService.create(req.body);
res.json(producto);
});
router.get("/:id", (req, res) => {
const producto = itemService.obtenerProducto(req.params.id);
if (producto) {
res.json(producto);
} else {
res.status(404).json({ error: "Producto no encontrado" });
}
});
router.put("/:id", (req, res) => {
const id = req.params.id;
const producto = itemService.actualizarProducto(id, req.body);
res.json(producto);
});
router.delete("/:id", (req, res) => {
const id = req.params.id;
itemService.eliminarProducto(id);
res.json({ message: "Producto eliminado" });
});
module.exports = router;
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
