0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

SequelizeでのバリデーションでInput欄枠に色を付ける

Last updated at Posted at 2022-01-28

はじめに

 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で追加した後に戻ってきます。

views/users/index.ejs
<!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・・はバリデーションに引っかかったときにクラスを変えるために追加

views/users/add.ejs
<!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は消しました。

routes/users.js
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」のみです。

/public/stylesheets/style.css
body {
  padding: 50px;
  font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
}

a {
  color: #00B7FF;
}
.red{
  outline:solid 2px red;
}

models

ここでデータの型とvalidate設定しています。

models/users.js
'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行くらいありますが、はっしょってます。

app.js
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 超入門 掌田 津耶乃 著

0
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?