JavaScriptでフォームバリデーションを行う方法

テーマ

こんにちは!!naoto555です。JavaScriptを使用してフォームバリデーションを行う方法について、本記事では詳しく解説していきます。フォームバリデーションは、ユーザーからの入力内容に対して、特定のルールに基づいて検証し、エラーがあればそれを表示する機能です。例えば、以下の画像に示している例では「メールアドレスなのに@マークが書いてないよ」というエラーがでています。

本記事では、JavaScriptのddEventListener()を使用したフォームバリデーションについて解説します。フォームの入力内容を取得し、正しいフォーマットに従っているかどうかをチェックし、エラーメッセージを表示する方法を紹介します。(2024.2記載)

事前準備

解説の前に、HTML/CSSで名前、メールアドレス、パスワードを入力する簡単なフォームを作成してみます。

HTML

<form id="myForm">
    <div>
        <label for="name">名前:</label>
        <input type="text" id="name" name="name">
    </div>
    <div>
        <label for="email">メールアドレス:</label>
        <input type="email" id="email" name="email">
    </div>
    <div>
        <label for="password">パスワード:</label>
        <input type="password" id="password" name="password">
    </div>
    <button type="submit">送信</button>
</form>

フォームが完成しました。

このままでは見栄えが少し悪いので、CSSを作成し少し見栄えを整えていきます。

CSS

form {
    display: block;
    width: 60%;
    margin: 40px auto;
    padding: 25px;
    background-color: #f2f2f2;
    border-radius: 10px;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
}


div {
    margin: 0 auto 20px;
    padding-right: 25px;
}


label {
    display: inline-block;
    width: 150px;
    font-weight: bold;
    color: navy;
}


input {
    width: 100%;
    padding: 10px;
    font-size: 16px;
    border-radius: 5px;
    border: 1px solid #ccc;
}

button[type="submit"] {
    display: block;
    margin-left: auto;
    padding: 10px 20px;
    background-color: lightblue;
    color: #fff;
    border: none;
    border-radius: 5px;
    margin-top: 20px;
}

button[type="submit"]:hover {
    opacity: 0.7;
}

 

これである程度見栄えが整いました。

バリデーションの種類と例

①必須項目の確認

JavaScript

var form = document.getElementById('myForm');

form.addEventListener('submit', (e)=>{
    //デフォルトの送信を止める
    e.preventDefault();

    //必須項目を確認する配列
    var requiredFields = ['name', 'email', 'password'];

    // 必須項目が入力されたかチェックする
    for(let field of requiredFields){
        var input = document.getElementById(field);

        if(input.value.trim() === ''){
            alert(`${input.name}は必須項目です`);
            return;
        }
    }
    
    form.submit();
});

 

formタグの要素をIDから取得して、要素の’submit’イベント(送信ボタンが押す)が発生したときに、{}内の処理(イベントハンドラ)を実行しています。addEventListenerに関しては過去の記事で使い方説明しているので、このあたりの内容詳しく知りたい方はこちらの記事ご参照下さい。

イベントハンドラでは、まず、”e.preventDefault()“で通常で送信処理を止めています。通常であればHTMLのフォームタグ内の<button type=”submit”>で定義されたボタンタグを押すとそのままフォーム送信されてしまうのをこのコードで防いでいます。

次に”requiredField”に以下の文字列を挿入し、それをfor文に入れてinputタグが未記入で送信ボタンを押した場合にアラートを出す処理を書いています。”.trim()”は文字列のスペースや改行などを削除するメソッドで、上記のコードでは取得した文字列のスペースや改行を削除したものが空白の場合にアラートを出す処理をしています。

また、for文の部分はfor…ofループという表現を使用しています。通常のfor文(for…in文)で書くと以下のような表現になるところを、for…ofループを使うことでインデックス変数(i)やループ回数の指定を使わずに反復処理できるため、以下に示す通常のfor文(for…in文)よりもfor…ofループのほうが、使い勝手が良くなっています。

通常のfor文(for…in文)

for(let i=0; i<requiredFields.length; i++){   
    var field = requireField[i];
    var input = document.getElementById(field);
    //以下、同文
}

 

完成画像
以下は、事前準備で用意した、HTMLで名前未入力で送信ボタンを押したときの画像です。

②メールアドレスの形式チェック

JavaScript

var emailInput = document.getElementById('email');
var emailValue = emailInput.value.trim();

var emailRegex = /^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;

if(!emailRegex.test(emailValue)){
    //エラー処理
}else{
    //正しい形式の場合の処理
}

 

多分、/^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/の部分(正規表現と呼ばれる部分)がなんのことか分からないかと思いますので、説明します。

\w+([-+.’]\w+)*“の部分
\w“の部分は、アルファベットの小文字のa~z、大文字のA~Zの文字列、0~9までの数字、アンダーバー記号を含む文字列を意味しています。
また、その後ろの”([-+.’]\w+)“の部分で”-aaaBBB”、”+aaaBBB”のような記号+文字列も許容しています。つまり、\w+([-+.’]\w+)の箇所では、(“文字列”)or(“文字列” + “記号” + “文字列”)になっているかをチェックしています。(“文字列”)or(“文字列” + “記号” + “文字列”)の形式になっていればOKですが、最初が文字列でなかったり文字列で終わっていない場合、記号が連続する場合はマッチしません。また、最後の”*“の部分は直前の文字の0回以上の繰り返しを意味していて、これにより、(“文字列” + {“記号” + “文字列”})の{}内の繰り返しを許容しています。
[マッチする文字列]
example
Example_MYMAIL0123_
example+example-example+example
[マッチしない文字列]
+example
example+++++example
example-example+

@“,”\w+([-.]\w+)*“,”$“の部分
@“はアットマークとマッチし、”\w+([-.]\w+)*“の部分はドメイン名とマッチします。”$“は文字列の末尾を意味しています。

メールアドレスの判別
上記ルールにマッチしたメールアドレスが入力されているかを、
emailRegex.test(emailValue)“で判別しています。test()メソッドでは渡された文字列が正規表現にマッチしているかを真偽値で返すメソッドになります。この場合は、”emailValue“が”emailRegex“で定義された形式にマッチしているかをマッチしていれば”true”、マッチしていなければ”false”で返します。

③電話番号の形式チェック

作成したHTMLに、電話番号の入力のインプットタグがなかったので追加し、以下のコードで電話番号入力のチェックのためのバリデーションを作成します。

<!-- 追加(ここから) -->
<div>
    <label for="tel">電話番号:</label>
    <input type="tel" id="tel" name="tel"> 
</div>
<!-- 追加(ここまで) -->

<script type="text/javascript">
    var telInput = document.getElementById('tel');
    var telValue = telInput.value.trim();

    var telRegex = /^0\d{1,4}-\d{1,4}-\d{3,4}$|^0\d{9,10}$|^\d{2,4}-\d{2,4}-\d{3,4}$/;

    if(!telRegex.test(telValue)){
        //エラー処理
    }else{
        //正しい形式のときの処理
    }
</script>

メールアドレスの形式チェック同様、”/^0\d{1,4}-\d{1,4}-\d{3,4}$|^0\d{9,10}$|^\d{2,4}-\d{2,4}-\d{3,4}$/“の部分で電話番号をチェックしています。
| “の縦線で区切られている部分はORを表していて、”/^0\d{1,4}-\d{1,4}-\d{3,4}$” OR “^0\d{9,10}$” OR “^\d{2,4}-\d{2,4}-\d{3,4}$/“の形式にマッチしているかをチェックしています。
例えば、
/^0\d{1,4}-\d{1,4}-\d{3,4}$“の場合
/^0”の部分で0から始まっているかチェックし、”\d{1,4}”では\dは数字を表し、{1,4}で数字が1桁から4桁であるとマッチするようになっています。つまり”/^0\d{1,4}-\d{1,4}-\d{3,4}$“でマッチする文字列は、以下のようなものにまります。
[マッチする文字列](※Xは0~9の数字)
03-XXXX-XXXX
0266-XXX-XXXX
[マッチしない文字列](※Xは0~9の数字)
033333-XXX-XXX  →033333が桁数オーバー
03-XXXXX-XXX     →XXXXXが桁数オーバー
03-ABCD-電話番号 →数字以外の文字列が入っている

また、”^0\d{9,10}$” OR “^\d{2,4}-\d{2,4}-\d{3,4}$/“では、-(ハイホン)なしで数字だけで入力した場合と固定電話だけでなく、携帯電話の番号を入れたときにエラーにならないようにしている。

電話番号の判別
上記ルールにマッチした電話番号が入力されているかを、
telRegex.test(telValue)“で判別しています。test()メソッドでは渡された文字列が正規表現にマッチしているかを真偽値で返すメソッドになります。この場合は、”telValue“が”telRegex“で定義された形式にマッチしているかをマッチしていれば”true”、マッチしていなければ”false”で返します。

パスワードの複雑性チェック

JavaScript

var passwordInput = document.getElementById('password');
var password = passwordInput.value;

var passwordRegex = /^(?=.*?[A-Z])(?=.*?[0-9])[a-zA-Z0-9]{8,}$/;

if(!passwordRegex.test(password)){
    //エラー処理
}else{
    //正しい形式の場合の処理
}

 

email、電話番号同様、パスワードも正規表現でパスワードの複雑性をチェックできます。

/^(?=.*?[A-Z])(?=.*?[0-9])[a-zA-Z0-9]{8,}$/“の解説

(?=.*?[A-Z])“:1文字以上の任意の文字(改行以外)が0回以上の出現を許容し、かつその中に大文字のアルファベットが含まれていることを確認します。 (?=...) は、肯定的先読みアサーションと呼ばれ、先読みした部分が一致する場合にマッチします。

(?=.*?[0-9])“:1文字以上の任意の文字(改行以外)が0回以上の出現を許容し、かつその中に数字が含まれていることを確認します。

[a-zA-Z0-9]{8,}“:8文字以上のアルファベットの小文字、大文字、数字から構成される文字列であることを表します。 {8,} は、8回以上の繰り返しを意味します。

以上より、パスワードに少なくともアルファベットの大文字と数字を1つ以上含み、8文字以上でパスワードが構成されているかをチェックできます。
電話番号、emailと同様に、”passwordRegex.test(password)“で形式にマッチしているかを判別しています。

実際にテストコードを作成してみる

前の項で紹介した、「バリデーションの種類と例」のコードを使って、テストコードを作成してみたいと思います。

作成コード

<!-- HTML部分 -->
<form id="myForm">
    <div>
        <label for="name">名前:</label>
        <input type="text" id="name" name="name">
    </div>
    <div>
        <label for="email">メールアドレス:</label>
        <input type="email" id="email" name="email">
    </div>
    <div>
        <label for="tel">電話番号:</label>
        <input type="tel" id="tel" name="tel">            
    </div>
    <div>
        <label for="password">パスワード:</label>
        <input type="password" id="password" name="password">
    </div>
    <button type="submit">送信</button>
</form>


<!-- JavaScript部分 -->
<script type="text/javascript">
    const form = document.getElementById('myForm');
    const nameInput = document.getElementById('name');
    const emailInput = document.getElementById('email');
    const telInput = document.getElementById('tel');
    const passwordInput = document.getElementById('password');


    form.addEventListener('submit', (e) => {
        e.preventDefault();

        const nameValue = nameInput.value.trim();
        const emailValue = emailInput.value.trim();
        const telValue = telInput.value.trim();
        const passwordValue = passwordInput.value;

        // 名前の入力チェック
        if (nameValue === '') {
            alert('名前を入力してください');
            return;
        }

        // メールアドレスの形式チェック
        const emailRegex = /^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
        if (!emailRegex.test(emailValue)) {
            alert('有効なメールアドレスを入力してください');
            return;
        }

        // 電話番号の形式チェック
        const telRegex = /^0\d{9,10}$/;
        if (!telRegex.test(telValue)) {
            alert('有効な電話番号を入力してください');
            return;
        }

        // パスワードの複雑性チェック
        const passwordRegex = /^(?=.*?[A-Z])(?=.*?[0-9])[a-zA-Z0-9]{8,}$/;
        if (!passwordRegex.test(passwordValue)) {
            alert('パスワードは大文字と数字を含む8文字以上で設定してください');
            return;
        }

        // フォームの送信
        form.submit();
    });
</script>

 

以上のコードで、JavaScriptを使ったバリデーションが完成しました。

完成図

バリデーション付きのフォームが完成しました。試しにパスワードを”password”と打って送信ボタンを押してみます。8文字以上は満足していますが、大文字と数字がないため期待通りアラートが出ています。

また、alertの代わりに下記に示す、"setCustomValidity"を使用すればダイアログでなくインプットタグからの吹き出しからエラーメッセージが出ているような描写も可能です。

JavaScript

form.addEventListener('submit', (e) => {
    e.preventDefault();
   
    //----------------------------------中略----------------------------------
   
    // メールアドレスの形式チェック
    const emailRegex = /^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
    if (!emailRegex.test(emailValue)) {
        emailInput.setCustomValidity('有効なメールアドレスを入力してください');
        return;
    }

    //----------------------------------中略----------------------------------
   
    // フォームの送信
    form.submit();
});