๐ ๊ณต๋ถํ๋ ์ง์ง์ํ์นด๋ ์ฒ์์ด์ง?
[CRUD์ ์ด์ฉํ File upload Web] (8) Datatables ๋ก ๋ค์ ํ์ด์ง ์ด๋ํ๊ธฐ & user ๋ฐ์ดํฐ html์ ๋์ฐ๊ธฐ ๋ณธ๋ฌธ
[CRUD์ ์ด์ฉํ File upload Web] (8) Datatables ๋ก ๋ค์ ํ์ด์ง ์ด๋ํ๊ธฐ & user ๋ฐ์ดํฐ html์ ๋์ฐ๊ธฐ
์ง์ง์ํ์นด 2023. 3. 11. 12:42<๋ณธ ๋ธ๋ก๊ทธ๋ DCodeMania ์ ์ ํ๋ธ๋ฅผ ์ฐธ๊ณ ํด์ ๊ณต๋ถํ๋ฉฐ ์์ฑํ์์ต๋ :-)>
=> CRUD App With Image Upload Using NodeJs, ExpressJs, MongoDB & EJS Templating Engine
๐ฅ datatables
https://datatables.net/download/
: ๊ฒ์๊ธฐ๋ฅ, ์ด๊ฑด์, ํ์ด์ง๋น๊ฑด์, ์ด์ /๋ค์ ํ์ด์ง ์ด๋, ์ปฌ๋ผ๋ณ ์ ๋ ฌ, ํ๋ ํฌ๋งท, ์ผ์ชฝ/๊ฐ์ด๋ฐ/์ค๋ฅธ์ชฝ ์ ๋ ฌ ๋ฑ์ ์ ๊ณต
๐ฅ CDN
: Content Delivery Nerwork์ ์ฝ์
: ์น์ฌ์ดํธ์ ์ ์์๊ฐ ์ฝํ ์ธ ๋ฅผ ๋ค์ด๋ก๋ํ ๋ ์๋์ผ๋ก ๊ฐ์ฅ ๊ฐ๊น์ด ์๋ฒ์์ ๋ค์ด๋ก๋ํ ์ ์๋๋ก ํ๋ ๊ธฐ์
๐ฅ MongoDB์ user Data ๋ฃ์ด์ง๊ณ , html์ ๋ฑ๋ก๋๋ ๊ณผ์
๐ง views/index.ejs
<%- include("layout/header") %>
<div class="container">
<div class="row my-4">
<div class="col-lg-12">
<!-- router ์ ์๋ locals.message ๊ฐ์ ธ์ด -->
<!--
1. <% %> : EJS ์์ ์์ค๋ด ์์ ์คํ๋์ง๋ง ๋ณด์ด์ง๋ ์๋ ํ๊ทธ
2. <%- %> : <% %> ํ๊ทธ์๋ ์กฐ๊ธ ๋ค๋ฅด๊ฒ HTML ์ฝ๋๋ฅผ ๋ ๊ฒ(Raw)๋ก ๋ณด์
3. <%= %> : ์ด์ค์ผ์ดํ ๋ฌธ์๋ฅผ ํฌํจ, ๋ค๋ฅธ ํ์ด์ง์์ ๋ฐ์์จ ๋ฐ์ดํฐ๋ฅผ ๋ฃ์ด์ค ๋
-->
<% if (message) { %>
<div class="alert alert-dismissible fade show alert-<%= message.type %>" role="alert">
<button class="btn-close" type="button" data-bs-dismiss="alert" aria-label="Close"></button>
<strong>
<%= message.message %>
</strong>
</div>
<% } %>
<div class="table-responsive">
<% if (users !="" ) { %>
<!-- ํ๋ฉด ํฌ๊ธฐ์ ๋ฐ๋ผ ํจ๊ณผ์ ์ผ๋ก ์ฝํ
์ธ ๊ฐ ํ์๋๋๋ก ํ
์ด๋ธ์ ์กฐ์ -->
<table class="table table-striped">
<!-- ํ
์ด๋ธ์ ์ด์ ๋จธ๋ฆฌ๊ธ์ธ ํ๋ค์ ์งํฉ -->
<thead class="table table-striped text-center my-3">
<tr class="table-dark">
<th>ID</th>
<th>Image</th>
<th>Name</th>
<th>E-mail</th>
<th>Phone</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<% users?.forEach((row, index)=> { %>
<tr class="align-middle">
<td>
<%= index %>
</td>
<td><img src="<%= row.image %>" width="50" class="img-thumbnail"></td>
<td>
<%= row.name %>
</td>
<td>
<%= row.email %>
</td>
<td>
<%= row.phone %>
</td>
<td>
<a href="/edit/<%= row._id %>" class="text-success"><i class="fas fa-edit fa-lg mx-1"></i></a>
<a href="/delete/<%= row._id %>" class="text-danger"><i
class="fas fa-trash fa-lg mx-1"></i></a>
</td>
</tr>
<% }) %>
</tbody>
</table>
<% } else { %>
<h1 class="text-center text-secondary mt-S">No users found in the databases!</h1>
<% } %>
</div>
</div>
</div>
</div>
<%- include("layout/footer") %>
๐ง views/layout/headr.ejs
<!DOCTYPE html>
<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=1.0">
<title>
<%= title %>
</title>
<!-- ๋ถํธํธ๋ฉ ์ฌ์ฉ -->
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.0.0-beta2/css/bootstrap.min.css"
integrity="sha512-aqT9YD5gLuLBr6ipQAS+72o5yHKzgZbGxEh6iY8lW/r6gG14e2kBTAJb8XrxzZrMOgSmDqtLaF76T0Z6YY2IHg=="
crossorigin="anonymous" referrerpolicy="no-referrer" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/css/all.min.css"
integrity="sha512-HK5fgLBL+xu6dm/Ii3z4xhlSUyZgTT9tuc/hSrtw6uzJOvgRr2a9jyxxT1ely+B+xFAmJKVSTbpM/CuL7qxO8w=="
crossorigin="anonymous" referrerpolicy="no-referrer" />
<!-- ๋ค์ ํ์ด์ง ์ด๋ํ๋ ํ
์ด๋ธ ์ฌ์ฉ -->
<link href="https://cdn.datatables.net/v/bs4/dt-1.13.3/datatables.min.css" rel="stylesheet" />
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container">
<a href="/" class="navbar-brand"><i class="fas fa-code me-2"></i>GANI</a>
<button class="navbar-toggler" data-bs-target="#my-nav" data-bs-toggle="collapse" aria-controls="my-nav"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div id="my-nav" class="collapse navbar-collapse">
<ul class="navbar-nav ms-auto">
<li class="nav-item active">
<a class="nav-link" href="/"><i class="fas fa-home me-1"></i>Home</a>
</li>
<li class="nav-item active">
<a class="nav-link" href="/add"><i class="fas fa-user-plus me-1"></i>Add user</a>
</li>
<li class="nav-item active">
<a class="nav-link" href="#"><i class="fas fa-globe me-1"></i>About</a>
</li>
<li class="nav-item active">
<a class="nav-link" href="#"><i class="fas fa-envelope me-1"></i>Contact</a>
</li>
</ul>
</div>
</div>
</nav>
๐ง views/layout/footer.ejs
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"
integrity="sha512-bLT0Qm9VnAYZDflyKcBaQ2gg0hSYNQrJ8RilYldYQ1FxQYoCLtUjuuRuZo+fjqhx/qtq/1itJ0C2ejDxltZVFg=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.0.0-beta2/js/bootstrap.bundle.min.js"
integrity="sha512-43iShtbiyImxjjU4a9rhXBy7eKtIsrpll8xKhe1ghKqh5NyfME8phZs5JRFZpRBe1si44WM3tNmnqMym7JRmDQ=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<!-- ์ด์ /๋ค์ ํ์ด์ง ์ด๋ -->
<script src="https://cdn.datatables.net/v/bs4/dt-1.13.3/datatables.min.js"></script>
<script>
// ํ์๋ ํ
์ด๋ธ์ ์ด๊ธฐํํ์๋ ํ
์ด๋ธ์ ์ด๊ธฐํ => ์ด์ /๋ค์ ํ์ด์ง ๊ธฐ๋ฅ ํด์ค
$(document).ready(function () {
$("table").DataTable({
order: [0, "desc"]
});
});
</script>
</body>
</html>
๐ง routes/routes.js
const express = require("express");
const router = express.Router();
const User = require("../models/user");
const multer = require("multer");
// image upload
var storage = multer.diskStorage({
// ํ์ผ์ด ์
๋ก๋๋ ๊ฒฝ๋ก ์ค์
destination: function (req, file, cb) {
cb(null, "./uploads");
},
// timestamp๋ฅผ ์ด์ฉํด ์๋ก์ด ํ์ผ๋ช
์ค์
filename: function (req, file, cb) {
cb(null, file.fieldname + "_" + Date.now() + "_" + file.originalname);
}
})
var upload = multer({
storage: storage,
}).single("image"); // ํ ๊ฐ์ ์ด๋ฏธ์ง ์ฒ๋ฆฌ
// Insert an user into database route
router.post("/add", upload, (req, res) => {
const user = new User({
name: req.body.name,
email: req.body.email,
phone: req.body.phone,
image: req.file.filename,
});
user.save().then((err) => {
// index.js ์ res.locals.message ์์
req.session.message = {
type: "success",
message: "User added successsfull!"
};
// ์ง์ ๋ ๋ค๋ฅธ URL๋ก ์ฌ์์ฒญ (ํ)
res.redirect("/");
}).catch((err) => {
res.json({ message: err.message, type: "danger" });
})
});
// Get all users route
router.get("/", (req, res) => {
// Query๋ฅผ ์ด์ฉํ ๋ ํ๋ก๋ฏธ์ค๋ฅผ ๋ฆฌํด๋ฐ๊ณ ์ถ๋ค๋ฉด exec() ๋ฉ์๋๋ฅผ ์ด์ฉ
// find()๋ฅผ ์คํํ์ฌ Query์ ์ธ์คํด์ค๋ฅผ ๋ฆฌํด
User.find({}).then((error, users) => {
res.render("index", {
title: "Home Page",
// ๊ถ๊ธ : ๋ ์ error ์กํ๋?
users: error
});
}).catch((error) => {
res.json({ message: error.message });
});
});
router.get("/add", (req, res) => {
res.render("addUsers", { title: "Add users" });
})
module.exports = router;
๐ง index.js
// imports
require("dotenv").config();
const express = require("express");
const mongoose = require("mongoose");
const session = require("express-session");
// express-session
// 1. ํ์ผ์ ์ ์ฅ
// 2. DB์ ์ ์ฅ
// 3. Memory ์ ์ ์ฅ
const app = express();
const PORT = process.env.PORT || 8000;
// Database ์ฐ๊ฒฐ
mongoose.connect(process.env.MONGODB_URI, { useNewUrlParser: true, useUnifiedTopology: true }); // useNewUrlParser : ์๋ฌ ๋ฐฉ์ง
const db = mongoose.connection;
db.on("error", (error) => console.log(error));
db.once("open", () => console.log("๐ Connected to the database!"));
// Middleware ์ฐ๊ฒฐ
app.use(express.urlencoded({ extended: false }));
app.use(express.json()); // JSONํํ์ ๋ฐ์ดํฐ๋ฅผ ํด์
app.use(session({
secret: process.env.SECRET, // ์ํธํ๋ฅผ ์ํ keygen. ๋ณดํต env์ ๋ฃ์ด์ ์ ๋ฌ
saveUninitialized: true, // ์ธ์
์ ์ ์ฅํ ๋ด์ญ์ด ์๋๋ผ๋ ์ฒ์๋ถํฐ ์ธ์
์ ์์ฑํ ์ง ์ค์
resave: false, // ์ธ์
์ ์ธ์ ๋ ์ ์ฅํ ์ง ์ค์ ํจ
cookie: { // ์ฟ ํค์ ์ ํจ์๊ฐ
maxAge: 86400000, // 24 hours (= 24 * 60 * 60 * 1000 ms)
},
})
);
// ๊ณตํต EJS ํ์ผ(header๋ footer)์์ ์ฌ์ฉํ ๋ฐ์ดํฐ๋ฅผ ์ธํ
app.use((req, res, next) => {
// ejs ํ์ผ์์ ์ฌ์ฉํ๋ ค๋ฉด 'res.locals.๋ณ์๋ช
= ๊ฐ' ์ ์ด์ฉ
res.locals.message = req.session.message;
delete req.session.message;
next(); // ์ฑ ๋ด์ ๊ทธ ๋ค์ ๋ฏธ๋ค์จ์ด ํจ์๊ฐ ํธ์ถ
});
// uploads ํด๋์ ์ฌ์ง html์ ๋ณด์ด๊ฒ ํ๊ธฐ
app.use(express.static("uploads"));
// set template engine
app.set("view engine", "ejs");
// router
app.use("", require("./routes/routes"));
app.get("/", (req, res) => {
res.send("Hello World");
});
app.listen(PORT, () => {
console.log(`server started at ๐ http://localhost:${PORT}`);
});
๊ทผ๋ฐ ์๊ธด๊ฑด router ์์ user ์ ๋ณด ๋๊ธฐ๋๋ฐ ์ error์์ user json ์ด ์กํ๊น~? ^_^