網頁
Sequelize 筆記
// db.js
const { Sequelize } = require('sequelize');
const sequelize = new Sequelize('database', 'root', '1234', {
dialect: 'mysql',
timezone: '+08:00',
define: {
underscored: true, // 欄位有下㡳線
freezeTableName: true, // 不要自動改變 table 名稱
},
});
module.exports = sequelize;
// app.js
sequelize
.sync()
.then(() => {
app.listen(3000, () => {
console.log('listening on port 3000');
});
})
.catch((err) => {
console.log(err);
});
// model
const TeamTaiwan = sequelize.define(
'teamTaiwan',
{ ... },
{ tableName: 'team_taiwan' }
);
module.exports = TeamTaiwan;
---
const TaiwanPlayer = sequelize.define(
'taiwanPlayer',
{ ... },
{ tableName: 'taiwan_player' }
);
module.exports = TaiwanPlayer;
// TeamTaiwan 跟 TaiwanPlayer 是一對多的關係
TeamTaiwan.hasMany(TaiwanPlayer);
TaiwanPlayer.belongsTo(TeamTaiwan);
新增 TaiwanPlayer 的 Foreign Key(team_taiwan_id),在程式裡會變成 teamTaiwanId
TaiwanPlayer.create({
name: formData.name,
teamTaiwanId: teamTaiwanId,
})
.then(...)
.catch(...);
有用到下面的 sequelize.fn, sequelize.col 語法時,取欄位值有二個方法:
TaiwanPlayer.findAll({
attributes: [[sequelize.fn('COUNT', sequelize.col('name')), 'count_name']],
})
---
JSON.parse(JSON.stringify(data[0]))
或
data[0].get().count_name
網頁
使用 JS 實做分頁
參考 Laravel 5 的分頁模式,11 頁以下全部顯示,12 頁以上會出現省略的點點記號。
const page = document.querySelector('#page');
const pageNum = 16;
const urlParams = new URLSearchParams(window.location.search);
const activePage = urlParams.get('page');
console.log('activePage:', activePage);
// 顯示頁數 11 以下
if (pageNum <= 11) {
let data = '';
for (let i = 1; i <= pageNum; i++) {
data += `<li class="page-item"><a class="page-link" href="/?page=${i}">${i}</a></li>`;
}
page.innerHTML = data;
}
// 顯示頁數 12 以上
if (pageNum > 11) {
let data = '';
if (activePage < 7) {
for (let i = 1; i <= pageNum; i++) {
if (i <= 8) {
data += `<li class="page-item"><a class="page-link" href="/?page=${i}">${i}</a></li>`;
}
if (i === pageNum - 2) {
data += `<li class="page-item"><a class="page-link" href="javascript:;">...</a></li>`;
}
if (i === pageNum - 1) {
data += `<li class="page-item"><a class="page-link" href="/?page=${pageNum - 1}">${pageNum - 1}</a></li>`;
}
if (i === pageNum) {
data += `<li class="page-item"><a class="page-link" href="/?page=${pageNum}">${pageNum}</a></li>`;
}
}
}
if (activePage >= 7 && Number(activePage) + 6 <= pageNum) {
for (let i = 1; i <= pageNum; i++) {
if (i === 1 || i === 2) {
data += `<li class="page-item"><a class="page-link" href="/?page=${i}">${i}</a></li>`;
}
if (i === 3) {
data += `<li class="page-item"><a class="page-link" href="javascript:;">...</a></li>`;
}
if (i >= activePage - 3 && i <= Number(activePage) + 3) {
data += `<li class="page-item"><a class="page-link" href="/?page=${i}">${i}</a></li>`;
}
if (i === pageNum - 2) {
data += `<li class="page-item"><a class="page-link" href="javascript:;">...</a></li>`;
}
if (i === pageNum - 1) {
data += `<li class="page-item"><a class="page-link" href="/?page=${pageNum - 1}">${pageNum - 1}</a></li>`;
}
if (i === pageNum) {
data += `<li class="page-item"><a class="page-link" href="/?page=${pageNum}">${pageNum}</a></li>`;
}
}
}
if (activePage >= 7 && Number(activePage) + 6 > pageNum) {
for (let i = 1; i <= pageNum; i++) {
if (i === 1 || i === 2) {
data += `<li class="page-item"><a class="page-link" href="/?page=${i}">${i}</a></li>`;
}
if (i === 3) {
data += `<li class="page-item"><a class="page-link" href="javascript:;">...</a></li>`;
}
if (i >= pageNum - 8) {
data += `<li class="page-item"><a class="page-link" href="/?page=${i}">${i}</a></li>`;
}
}
}
page.innerHTML = data;
}
網頁
使用 express-validator
// router
const adminValidator = require('../validators/admin.validator');
...
router.post(
'/shop-type/create',
adminValidator.checkShopTypeFormData(),
shopTypeController.createShopType
);
// admin.validator.js
const { body } = require('express-validator');
function checkShopTypeFormData() {
return [body('name').trim().notEmpty().withMessage('請輸入商店類別')];
}
function checkShopFormData() {
return [
body('name').trim().notEmpty().withMessage('請輸入商店'),
body('phone').trim().notEmpty().withMessage('請輸入電話'),
body('note').optional().trim(),
body('type').isNumeric().withMessage('請選擇類別'),
];
}
module.exports = { checkShopTypeFormData, checkShopFormData };
// controller
const { matchedData, validationResult } = require('express-validator');
...
const result = validationResult(req);
if (!result.isEmpty()) {
ShopType.findAll()
.then((shopTypeList) => {
res.render('admin/shop/createShopForm', {
errors: result.array(),
old: req.body,
shopTypeList,
});
})
.catch((err) => {
console.log(err);
});
} else {
const formData = matchedData(req);
ShopType.findByPk(formData.type)
.then((data) => {
if (data === null) {
res.send('404 Not Found');
return;
}
return Shop.create({
name: formData.name,
phone: formData.phone,
note: formData.note,
shopTypeId: formData.type,
});
})
.then((data) => {
if (data) {
res.redirect('/admin/shops');
}
})
.catch((err) => {
console.log(err);
});
}
// view
<% if (errors.length > 0) { %>
<div>
<% errors.forEach((err) => { %>
<p><%= err.msg %></p>
<% }) %>
</div>
<% } %>