Lập trình MVC trong NodeJS

Lập trình MVC trong NodeJS hướng dẫn bạn cách thức phát triển website trong NodeJS với mô hình lập trình MVC.

Đôi điều về web Framework Express

Express là module rất phổ biến trong thế giới NodeJS, nó  giúp web dev tạo nên các chức năng cơ bản cho project mà không phải thực hiện nhiều việc thủ công.  Website của express là http://expressjs.com  

Bạn nên cài đặt express ở chế độ global, để sử dụng nó cho việc tạo project ở máy local nhanh hơn. Ngoài express, module express-generator cũng hết sức cần thiết cài vào, vì nó giúp bạn phát sinh các file và folder cần dùng lúc bắt đầu project. Thực hiện cài đặt như sau:

  1. Mở command line
  2. Gõ  lệnh npm install -g express
  3. Tiếp theo gõ lệnh  npm -g install express-generator

1. Tạo project với express

Vào command line và chuyển đến folder chứa project rồi chạy lệnh:

express --ejs LabTest

Bạn sẽ thấy folder LabTest xuất hiện các folder và file trong đó

labtest
labtest_files

Trong folder project có file app.js , đây là file chính, giống file main trong C++.  Express còn tạo 2 module routes/index và routes/users để xử lý các request HTTP.  Hàm app.set() thường thấy trong code dùng để gán thông số cho project và các module. .

labtest_files-2

Như hình trên, bạn thấy các thư viện cần thiết đã được nhúng, đã set sẵn view engine cũng thiết lặp, folder views và folder public đã chỉ định. 3 controller indexRouter và usersRouter cũng đã được khai báo và chỉ định.

labtest_files-3

File www trong folder bin đã cũng đã listen sẵn ở port 3000 cho bạn.

labtest_files-4

File package.json đã chỉ định start mặc định file bin/www

2. Cài module cho project

Chuyển vào folder project rồi chạy lệnh : npm install để cài thêm các chức năng cơ bản khác nhé.

3. Chạy project

Giờ thì đã có cấu trúc folder cùng các module cơ bạn, chạy project thôi. Chạy 1 trong 2 lệnh npm start hoặc node bin/www

Test: http://localhost:3000

chay-nodejs-voi-exoress

Mô hình MVC

MVC là mô hình thường được dùng hiện nay để phát triển các webite. Vì MVC giúp tổ chức tách bạch giữa các thành phần quan trọng trong dự án:  điều khiển (controller), xử lý dữ liệu (model) và hiển thị dữ liệu (view).

Controller trong mvc

Controller được tạo ra để thực thi các yêu cầu từ user,  controller thực hiện tiếp nhận tham số, gọi các hàm trong model, nạp các view cần thiết… Trong NodeJS , routes đóng vai trò như controller.

Model trong mvc

Model dùng để cung cấp dữ liệu, thực hiện kết nối, trích lọc, chèn, chỉnh sửa dữ liệu trong database, tương tác với file system, network.

View trong mvc

Mỗi view là một trang web hiển thị dữ liệu gì đó. Dữ liệu mà view hiển thị do controller cung cấp (controller lấy từ model để đưa cho view).

Việc tách riêntg vai trò của Controler, Model và View giúp cho team phân định rõ ràng các công việc xử lý nghiệp vụ, xử lý dữ liệu và trình bày dữ liệu. Do vậy việc cập nhật chỉnh sửa một thành phần không làm ảnh hưởng đến các thành phần khác.

Mô hình MVC trong Express

Lập trình MVC trong NodeJS tức bạn sẽ tạo nên các chức năng cho website quy ước của MVC. Theo đó, các việc xử lý request, hiển thị dữ liệu , xử lý dữ liệu phải tách bạch ra theo quy định.

Module express-generator giúp bạn tạo project đã gần giống với tổ chức MVC, như folder views chứa các file view để hiện dữ liệu, folder routes dùng để xử lý các đường path chính là thành phần controller trong MVC. Bạn cần tạo thêm thành phần model nữa để xử lý dữ liệu.

Để hiểu rõ lập trình MVC trong NodeJS là thế nào, chúng ta sẽ thực hiện một ví dụ lớn nhé. Sau đây là phần hướng dẫn tạo controller, model, view để quản trị dữ liệu trong table có tên là loai (sách).

Tạo controller trong nodejs

– Tạo file routes/loai.js

– Định nghĩa các route cho các action sẽ thực hiện list record, addnew, store, edit, update, delete

var express = require('express');
var router = express.Router();

router.get('/', function(req, res, next) {
    res.send('Danh sách loại sách');  
});
router.get('/addnew', function(req, res, next) {
    res.send('Form thêm loại sách'); 
});
router.post('/store', function(req, res, next) {
    //nhận dữ liệu từ addnew để thêm record vào db
});
router.get('/edit/:id', function(req, res, next) {
  var id = req.params.id;
  res.send('Form chỉnh loại sách' + id);
});
router.post('/update', function(req, res, next) {
    //nhận dữ liệu từ edit để cập nhật vào db
});
router.get('/delete/:id', function(req, res) {
  var id = req.params.id;
  res.send('Xóa loai');
});

module.exports = router;

– Mở app.js và thêm code khai báo route cho controller

var loaiRouter = require('./routes/loai');
app.use('/loai', loaiRouter);

Test các route, nếu thấy các chữ trong controller hiện ra là đúng.

http://localhost:3000/loai/
http://localhost:3000/loai/addnew
http://localhost:3000/loai/edit/1
http://localhost:3000/loai/delete/1

Tới đây đã tạo controller xong , bạn biết cách tạo controller ,tạo đường dẫn cho các chức năng rồi đó.

Tạo model

Thành phần model giúp tương tác với các hệ thống chứa dữ liệu.

– Mở command line, chuyển vào folder project
– Tạo folder tên models để chứa các model sẽ tạo
– Cài module mysql
– Tạo file models/database.js và code:

//Database trả về kết nối với cơ sở dữ liệu
var mysql = require('mysql');
var db = mysql.createConnection({
   host: 'localhost', user: 'root', password: '', 
   database: 'labnodejs'
}); 
db.connect(() => console.log('Da ket noi database !'));
module.exports = db; 
//lệnh exports để xuất (public) ra, cho ngoài module dùng được db

Nhúng model vào controller:

-Ở đầu controller loai, chèn model vào

var db=require('../models/database');

Chức năng hiện danh sách record

– Code trong route / của controller loai

router.get('/', function(req, res, next) {    
    let sql = `SELECT * FROM loai`;
    db.query(sql, function(err, data) {      
        res.render("loai_list",{list:data});    
    }); 
});

– Tạo view:

Tạo file views/loai_list.ejs để hiển thị các record lấy được từ db

<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">

<div class="container col-8">
<table class="table table-bordered">
    <tr>
        <th>id</th>
        <th>Tên loại</th>
        <th>Thứ tự</th>
        <th>Ẩn hiện</th>
    </tr>
    <% for (let c of list ) {  %>
    <tr>
        <td><%= c.id %> </td>        
        <td><%= c.tenLoai %> </td>
        <td><%= c.thuTu %> </td>
        <td><%= c.anHien==1 ? "Đang hiện" : "Đang ẩn"%> </td>
    </tr>
    <% } %>
  </ul>
</div>

– Test: http://localhost:3000/loai/

Chức năng hiện form thêm mới

– Code trong route addnew của controller loai

router.get('/addnew', function(req, res, next) {
    //res.send('Form thêm loại sách'); 
    res.render("loai_them");
});

– Tạo view:

Tạo file views/loai_addnew.ejs, trong view có form với method là post và trỏ lên action store

<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">

<div class="container">
<form class="col-6 border border-dark rounded p-3 m-auto" action="/loai/store" method="POST">
    <div class="form-group mb-3">
        <label for="tenLoai">Tên loại</label>
        <input class="form-control bg-info" name="tenLoai" id="tenLoai">
    </div>
    <div class="form-group mb-3">
        <label for="thuTu">Thứ tự</label>
        <input class="form-control bg-primary" name="thuTu" id="thuTu">
    </div>
    <div class="form-group mb-3">
        <label>Ẩn hiện</label>
        <input type="radio" name="anHien" value="1" checked> Hiện &nbsp; &nbsp; 
        <input type="radio" name="anHien" value="0"> Ẩn
    </div>
    <div class="form-group mt-3 ">       
        <button type="submit" class="btn btn-dark px-4  py-2 text-white"> LƯU DATABASE </button>
    </div>
</form>    
</div>

– Test: http://localhost:3000/loai/addnew

Chức năng lưu form vào database

– Code trong route store của controller loai

router.post('/store', function(req, res, next) {
    //nhận dữ liệu từ addnew để thêm record vào db
    let tl = req.body.tenLoai;
    let t = req.body.thuTu;
    let ah = req.body.anHien;     
    loai = { tenLoai:tl, thuTu:t, anHien:ah}
    db.query('insert into loai SET ?', loai, function(err, data) {
        if (err) throw err;
        res.redirect("/loai/");
    });   
});

Test lại từ form, khi submit sẽ thấy có dữ liệu mới

Chức năng hiện form edit 1 record

– Code trong route edit của controller loai

router.get('/edit/:id', function(req, res, next) {  
  var id = req.params.id;   
  let sql = `SELECT id, tenLoai, thuTu, anHien FROM loai where id=${id}`;
  db.query(sql, function(err, data) {    
    res.render("loai_chinh", { loai:data[0]});    
  });
});

– Tạo view:

a. Save as file loai_addnew. thành loai_edit.ejs
b. Chỉnh thuộc tính action của form từ store thành update
c. Hiện thông tin record trong form. Tham khảo hình sau

d. Thêm code sau vào trong form để giữ id của loại cần cập nhật, chút nữa sẽ dùng khi lưu database

<input type="hidden" name="id" value="<%=loai.id%>">

e. Test: http://localhost:3000/loai/edit/1

Code cập nhật record vào database

– Code trong route update của controller loai:

router.post('/update/', function(req, res, next) {
     //nhận dữ liệu từ edit để cập nhật vào db
     let id = req.body.id;     
     let tl = req.body.tenLoai;
     let t = req.body.thuTu;
     let ah = req.body.anHien;      
     db.query(`UPDATE loai SET tenLoai=?,thuTu=?, anHien=? WHERE id = ?`,  [tl, t,ah, id], 
     function(err, data) {    
        if (data.affectedRows==0) {
            console.log(`Không có id loại ${id} để cập nhật`);
        }
        res.redirect("/loai/");
    })
});

– Test: nhập giá trị mới trong form và lưu, sẽ thấy tác dụng

Chức năng xóa 1 record trong database

– Code trong route delete của controler loai

router.get('/delete/:id', function(req, res) {
  let id = req.params.id;
  let sql= `DELETE FROM loai WHERE id = ?`;
  db.query(sql, [id], function(err, data) {    
    if (data.affectedRows==0) {
        console.log(`Không có loại ${id} để xóa`); 
    }
    res.redirect('/loai');
  })
});

– Test

Lập trình MVC trong NodeJS giúp bạn thực hiện công việc theo khuôn mẫu, nhờ đó làm nhanh hơn, sự tách bạch các thành phần giúp dễ dò lỗi, dễ chia việc trong team…

À, bài cần phải có kiến thức kết nối database trong NodeJS, bạn cần đọc bài Làm việc với mysql trong NodeJS trước đã nhé


Bài tập: thực hiện luyện tập mvc tương tự như bài học nhưng với table sach như sau: