はじめに
Node.js + Express + sequelizeを勉強中です。フォームからレコード追加するところでバリデーション作成しました。バリデーションにひっかかた際テキストでの表示しかなかったので、ユーザービリティを上げるために、エラーのでた入力欄に色をつけようと思いました。検索しても出てこなかったので、備忘録も兼ね投稿しました。
sequelizeとは
Node.js用のORMライブラリ。
ORMはザックリ言うと「関数やオブジェクトを使って直感的にデータベースを操作しようぜ」なこと。
(参照)Sequelizeとは?【Node.js】
環境
- windows10
- node 16.13.1
- express 4.16.1
- ejs 2.6.1
- sqlite3 5.0.2
- sequelize 6.14.0
- sequelize-cli 6.4.1
- bootstrap 4.3.1(CDNです)
環境のインストール、設定などは済んでいるものとします
コード
indexページ
データベース一覧画面、/addで追加した後に戻ってきます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta http-equiv="content-type" content="text/html" charset="utf8"/>
<title><%= title %></title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" crossorigin="anonymous">
<link rel="stylesheet" href="/stylesheets/style.css">
</head>
<body class="container">
<header><h1 class="display-4"><%= title %></h1></header>
<div role="main">
<table class="table">
<% for(let co of content){ %>
<tr>
<th><%= co.id %></th>
<td><%= co.name %></td>
<td><%= co.mail %></td>
<td><%= co.age %></td>
</tr>
<% } %>
</table>
</div>
</body>
</html>
addページ
データベースにレコードを追加するejs
className,classPass・・はバリデーションに引っかかったときにクラスを変えるために追加
<!DOCTYPE html>
<html lang="ja">
<head>
<meta http-equiv="content-type" content="text/html" charset="utf8"/>
<title><%=title %></title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" crossorigin="anonymous">
<link rel="stylesheet" href="/stylesheets/style.css">
</head>
<body class="container">
<header><h1 class="display-4"><%=title %></h1></header>
<div role="main">
<ol class="text-danger">
<% if(err !=null){ for (let e of err.errors){ %>
<li><%= e.message%></li>
<% }}%>
</ol>
<form action="/users/add" method="post">
<div class="form-group">
<label for="name">NAME</label>
<input type="text" name="name" id="name" class="<%= className %>" value="<%= form.name %>">
</div>
<div class="form-group">
<label for="pass">PASSWORD</label>
<input type="text" name="pass" id="pass" class="<%= classPass %>" value="<%= form.pass %>">
</div>
<div class="form-group">
<label for="mail">Mail</label>
<input type="text" name="mail" id="mail" class="<%= classMail %>" value="<%= form.mail %>">
</ul>
</div>
<div class="form-group">
<label for="age">Age</label>
<input type="number" name="age" id="age" class="<%=
classAge %>" value="<%= form.age %>">
</div>
<input type="submit" value="追加" class="btn btn-primary">
</form>
</div>
</body>
</html>
JavaScript
crud作ったのですが、今回の記事には関係ないのでedit、deleteは消しました。
const express = require('express');
const router = express.Router();
const db = require('../models');
/* GET users listing. */
router.get('/', (req, res, next) => {
let data={};
db.User.findAll().then(usrs =>{
data ={
title:"Users/Index/Sequelize",
content:usrs
}
res.render('users/index',data);
})
});
//add
router.get('/add',(req,res,next)=>{
let data ={
title:"Users/Add",
form:new db.User(),
err:null,
className:"form-group",
classPass:"form-group",
classMail:"form-group",
classAge:"form-group",
}
res.render('users/add',data);
});
router.post('/add',(req,res,next)=>{
const form ={
name:req.body.name,
pass:req.body.pass,
mail:req.body.mail,
age:req.body.age,
}
db.sequelize.sync()
.then(()=>db.User.create(form)
.then(usr=>{
res.redirect('/users');
})
.catch(err=>{
let data={
title:"Users/Add",
form:form,
err:err,
};
// エラーのあるinputの枠を赤にする
let errPath =err.errors.map(item => item.path);//errのpathを取り出し
//class名を変えることでCSSを変更
//取り出したpathがある→ エラー有り→ 色を赤にする
data.className = errPath.includes("name") ? "form-group red" : "form-group";
data.classPass = errPath.includes("pass") ? "form-group red" : "form-group";
data.classMail = errPath.includes("mail") ? "form-group red" : "form-group";
data.classAge = errPath.includes("age") ? "form-group red" : "form-group";
res.render('users/add',data);
})
)
});
module.exports = router;
CSS
今回の投稿内容に関係するのは「.red」のみです。
body {
padding: 50px;
font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
}
a {
color: #00B7FF;
}
.red{
outline:solid 2px red;
}
models
ここでデータの型とvalidate設定しています。
'use strict';
module.exports = (sequelize, DataTypes) => {
const User =sequelize.define('User',{
name: {
type:DataTypes.STRING,
validate:{
notEmpty:true
}
},
pass:{
type:DataTypes.STRING,
validate:{
notEmpty:true
}
},
mail:{
type:DataTypes.STRING,
validate:{
isEmail:true
}
} ,
age:{
type:DataTypes.INTEGER,
validate:{
isInt:true,
min:0,
max:130
}
}
},{});
User.associate=function(models){};
return User;
};
appファイル
/root/usersでデータベース表示されるようにしています。
40行くらいありますが、はっしょってます。
var users = require('./routes/users');
app.use('/users',users);//「/users」にアクセスでデータベース表示
つまった所
前振り長かったですが、書きたかったのはここです!!
バリデーションした結果を動的にかえるのに最初
data.classAge = err.get('age')[0] ? "form-group red" : "form-group";
としたのですが、うまくいかず・・・
一度、エラーのpathを取り出して、再度判定したらうまくいきました。
//errのpathを取り出し
let errPath =err.errors.map(item => item.path);
//取り出したpathがある→ その項目にエラー有り→ クラス変更(色を赤にする)
data.classPass = errPath.includes("pass") ? "form-group red" : "form-group";
終わりに
codepen使おうと思ったのですが、EJSの<% %>タグは使えないみたいで、コード貼りました。
コードが長くなったので、概要をつかみにくいと自分でも思います。何かいい方法があれば教えてください。
参考文献
Node.js 超入門 掌田 津耶乃 著