画面遷移をせずにユーザー新規登録機能を作ってみました。
そこまで大した出来ではないです。
(実は理想としていたものより少々乖離しています。)
node.jsやjQueryの導入はこちらでは省いています。
また、新規登録、ログインモーダル以外の要素もありません。ご了承ください。
node.jsのバージョンは v14.15.4
です。
また、MySQLを使用しています。
1.必要なものをインストール
$ npm install express //expressをインストールします
$ npm install mysql //mysqlと接続できます
$ npm install express-session //登録機能です
$ npm install bcrypt //パスワードをハッシュ化してくれる機能です
これでインストールは以上です。
今回、ユーザー新規登録には、
username
, email
, password
の情報が必須となる設定にしています。
2.ルーティングのコードを書いていく
ディレクトリ構造は以下のようになっております
(node_modulesなどは省略しています。)
registation_app/
├ public/
│ ├ css/
│ │ └style.css/
│ ├ script.js/
│ └ validate.js/
├ views/
│ ├ log_in.ejs/
│ ├ sign_up.ejs/
│ ├ top.ejs/
│ └ uniq_error.ejs/
└ app.js/
// インストールしたものを適用させます
const express = require('express');
const mysql = require('mysql');
const session = require('express-session');
const app = express();
const bcrypt = require('bcrypt');
app.use(express.static('public'));
app.use(express.urlencoded({extended: false}));
// DBと接続します
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'パスワードを入力',
database: 'DB名を入力'
});
// トップ画面のルーティング
app.get('/', (req, res) => {
res.render('top.ejs');
});
// 重複するメールアドレスがある場合の画面遷移
app.get('/uniq_error',(req,res) =>{
res.render('uniq_error.ejs');
});
// 新規登録のルーティング
app.post('/sign_up',
(req, res, next) => {
const email = req.body.email;
connection.query(
'SELECT * FROM users WHERE email = ?',
[email],
(error, results) => {
if (results.length > 0) {
res.render('uniq_error.ejs');
} else {
next();
}
}
);
},
(req,res) => {
bcrypt.hash(password,10,(error,hash) => {
connection.query(
'INSERT INTO users (username, email, password) VALUES (?, ?, ?)',
[username, email, hash],
(error, results) => {
req.session.userId = results.insertId;
req.session.username = username;
res.redirect('/');
}
);
});
});
// ログインのルーティング
app.post('/log_in', (req, res) => {
const email = req.body.email;
connection.query(
'SELECT * FROM users WHERE email = ?',
[email],
(error, results) => {
if (results.length > 0) {
const plain = req.body.password;
const hash = results[0].password;
bcrypt.compare(plain,hash,(error,isEqual) => {
if(isEqual){
req.session.userId = results[0].id;
req.session.username = results[0].username;
res.redirect('/');
} else {
res.redirect('/');
}
});
} else {
res.redirect('/');
}
}
);
});
// ログアウトのルーティング
app.get('/log_out', (req, res) => {
req.session.destroy(error => {
res.redirect('/');
});
});
// ローカルホスト3000に接続
app.listen(3000);
});
3.トップ画面などのコーディング
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>registration_APP</title>
<link rel="stylesheet" href="/css/style.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script type="text/javascript" src="script.js"></script>
<script type="text/javascript" src="validate.js"></script>
</head>
<body>
<header>
<div class="header-wrapper" >
<a href="/" class="header-logo-left">registration_APP</a>
<% if (locals.isLoggedIn) { %>
<a class="header-logo-right" href="/log_out">ログアウト</a>
<% } else { %>
<div>
<a class="header-logo-right login-show">ログイン</a>
<a class="header-logo-right signup-show">新規登録</a>
<% } %>
</div>
</div>
</header>
<%- include('sign_up'); %>
<%- include('log_in'); %>
</body>
</html>
<%- include('sign_up'); %>
で新規登録モーダル
<%- include('log_in'); %>
でログインモーダルを呼び出します。
ある特定のページでのみモーダルを出現させるのであればこの記述をする必要はありませんが、
複数のページでモーダルを出したい場合、このようにすると使いまわせるので便利です。
//新規登録モーダル
<div class="signup-modal-wrapper" id="signup-modal">
<div class="modal">
<div id="signup-close-modal">
<i class="fa fa-2x fa-times"></i>
</div>
<div id="signup-form">
<h2>新規登録</h2>
<form action="/sign_up" method="post" id="sign_up-form">
<p class="error-message" id="sign_up-username-error-message"></p>
<input class="form-control" type="text" placeholder="ユーザー名" name="username" id="sign_up-username">
<p class="error-message" id="sign_up-email-error-message"></p>
<input class="form-control" type="text" placeholder="メールアドレス" name="email" id="sign_up-email">
<p class="error-message" id="sign_up-password-error-message"></p>
<input class="form-control" type="password" placeholder="パスワード" name="password" id="sign_up-password">
<input id="submit-btn" type="submit" value="登録する">
</form>
</div>
</div>
</div>
//ログインモーダル
<div class="login-modal-wrapper" id="login-modal">
<div class="modal">
<div id="login-close-modal">
<i class="fa fa-2x fa-times"></i>
</div>
<div id="login-form">
<h2>ログイン</h2>
<form action="/log_in" method="post">
<input class="form-control" type="text" placeholder="メールアドレス" name="email">
<input class="form-control" type="password" placeholder="パスワード" name="password">
<input id="login-btn" type="submit" value="ログインする">
</form>
</div>
</div>
</div>
これでトップ画面で二種類のモーダルをだせるようになりました。
(この段階では二種類のモーダルは現れた状態になっています。)
この後CSSを使ってモーダルを隠し、jQueryで表示させるアクションを作成します。
4.CSSをコーディング
CSSは全て書くととても長くなるので、必要最低限のところだけ
モーダルの大きさや文字の大きさ、背景色などはお好みで。
/* ヘッダーの『新規登録』『ログイン』部分 */
.header-logo-right {
display: inline;
}
.header-logo-right:hover {
cursor: pointer;
}
/* モーダル部分 */
.signup-modal-wrapper,.login-modal-wrapper{
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 100;
display: none;
}
.modal {
position: absolute;
top: 20%;
left: 34%;
background-color: #e6ecf0;
padding: 20px 0 40px;
border-radius: 10px;
width: 450px;
height: auto;
text-align: center;
}
.fa-times {
position: absolute;
top: 12px;
right: 12px;
color: rgba(128, 128, 128, 0.46);
cursor: pointer;
}
#signup-form,#login-form{
width: 100%;
}
これで新規登録、ログインボタンにカーソルを合わせるとポインタが変わります
さらにモーダル部分は隠れました。
それではjQueryを使ってモーダルが現れるように処理しましょう。
5.Jqueryをコーディング
$(function(){
$('.signup-show').click(function(){
$('#signup-modal').fadeIn();
});
$('#signup-close-modal').click(function(){
$('#signup-modal').fadeOut();
});
});
$(function(){
$('.login-show').click(function(){
$('#login-modal').fadeIn();
});
$('#login-close-modal').click(function(){
$('#login-modal').fadeOut();
});
});
これで、『新規登録』を押すと『新規登録モーダル』が
『ログイン』を押すと『ログインモーダル』が出るようになりました。
これで、新規登録並びにログインモーダルが完成です。
・・・と言いたい所さんですが、このままだと空白でも登録ができてしまいます。
と言うわけでバリデーションをかけていきましょう
6.バリデーションをかける
今回はjQuery側でバリデーションチェックをします。
挙動としては、入力に問題がある場合、送信はできず問題箇所にエラー文が出るようにします。
$(function() {
$('#sign_up-form').submit(function(){
var usernameValue = $('#sign_up-username').val();
var emailValue = $('#sign_up-email').val();
var passwordValue = $('#sign_up-password').val();
var errorCount = 0;
if(usernameValue === ""){
$('#sign_up-username-error-message').text('ニックネームを入力してください');
errorCount += 1;
} else {
$('#sign_up-username-error-message').text('');
}
if(emailValue === ""){
$('#sign_up-email-error-message').text('メールアドレスを入力してください');
errorCount += 1;
} else if(!emailValue.match(/^[a-zA-Z0-9_.+-]+@([a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]*\.)+[a-zA-Z]{2,}$/)){
$('#sign_up-email-error-message').text('メールアドレスが正しくありません');
errorCount += 1;
} else {
$('#sign_up-email-error-message').text('');
}
if(passwordValue === ""){
$('#sign_up-password-error-message').text('パスワードを入力してください');
errorCount += 1;
} else if(!passwordValue.match(/^(?=.*[a-zA-Z])(?=.*[0-9])[0-9a-zA-Z]{6,}$/) ){
$('#sign_up-password-error-message').text('パスワードは半角英数字6文字以上が必要です');
errorCount += 1;
} else {
$('#sign_up-password-error-message').text('');
}
if(errorCount !== 0){
return false;
}
});
});
これでバリデーションチェックができます。
解説としてはerrorCount
を0と最初に定義し、問題箇所1つにつきerrorCount
が1上昇していきます。
そして最後、errorCountが
0ではない場合送信できないように設定してあります。
そして全てのチェックが通ればerrorCount
は0なので送信し、ユーザー登録できる。
と言う仕掛けになっております。
これにて完成です。
と思ったら間違えです。
このままだと同じメールアドレスが登録できてしまいます。
ここから先が私の作りたかったモーダルとの理想と実力の無さが出た場所でした。
7.実現したかった内容
ここで同じアドレスが登録されている場合にもerrorCount
を1上昇させる処理をしたかったのですが、
ajax通信が何をやってもうまくいきませんでした。
jQuery単体では厳しいようで、PHPが必要なようです。
(jQueryだけでどうにかならないか色々勉強中です。)
仕方ないので、node.js側で同じメールアドレスがある場合は弾き、アラートを出す妥協案にしましたが、これまた失敗。
理由はnode.jsではalertメソッドが使えないようです。
8.苦し紛れに出した自分なりの答え
アラートが出せずにしばらく考え、出した結論が
『既に登録されているメールアドレスがあるため登録できませんでした』
と書かれたページへ遷移することでした。
コードで言うと、最初のapp.jsに既に記述してありますが、再び記述すると
app.post('/sign_up',
(req, res, next) => {
const email = req.body.email;
connection.query(
'SELECT * FROM users WHERE email = ?',
[email],
(error, results) => {
if (results.length > 0) {
res.render('uniq_error.ejs');
} else {
next();
}
}
);
こちらの部分になります。
これで重複するメールアドレスの場合はuniq_error.ejs
に遷移します。
ちなみにuniq_error.ejs
には
『既に登録されているメールアドレスがあるため登録できませんでした』
の文字しかありません。
9.終わりに
バリデーションチェックまでは苦戦しながらも進められたのですが、メールアドレスの重複チェックで躓き、数十時間もがき苦しみました。
まだまだ理解が足りない証拠ですね。
PHPの知識もそのうち入れたいと思います。