Skip to main content

フォームとバリデーション

この章で得られるスキル:

  • ✅ バリデーションの必要性を説明できる
  • required属性で必須入力を指定できる
  • minlength/maxlengthで文字数制限を指定できる
  • min/maxで数値範囲を指定できる
  • pattern属性で正規表現バリデーションを指定できる
  • placeholder属性で入力例を表示できる

Step 0: まず体験してみよう

説明の前に、まず バリデーションがないと何が困るのか を体験しよう。

シナリオ:会員登録フォーム

以下のような会員登録フォームがあるとする。

バリデーションがない場合の問題:

  1. 空欄で送信できる
    • ユーザー名を入力せずに登録できてしまう
  2. 不正なメールアドレスを入力できる
    • 「abc」だけでも登録できてしまう
  3. 短すぎるパスワードを設定できる
    • 「1」のような1文字のパスワードでも登録できてしまう

やってみよう:バリデーションなしのフォームを試す

以下のフォームで、何も入力せずに「登録」ボタンを押してみよう。空欄のまま送信できてしまう。

<h3>バリデーションなし</h3> <form action="#" method="POST"> <label>ユーザー名:<input type="text" name="username"></label><br> <label>メールアドレス:<input type="text" name="email"></label><br> <label>パスワード:<input type="text" name="password"></label><br> <button type="submit">登録</button> </form> <p>※ 空欄でも送信できてしまう</p>body { font-family: sans-serif; padding: 20px; } label { display: block; margin-bottom: 10px; } input { padding: 8px; border: 1px solid #ccc; border-radius: 4px; margin-left: 10px; } button { background-color: #007bff; color: white; padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; }

なぜバリデーションが必要なのか?

バリデーションがないと、空欄や不正なデータが送信されてしまう。サーバー側でエラーになるか、データベースに不正なデータが保存されてしまう。

やってみよう:バリデーションありのフォームを試す

次に、バリデーションを追加したフォームを試そう。空欄で送信しようとすると、エラーメッセージが表示される。

<h3>バリデーションあり</h3> <form> <label>ユーザー名:<input type="text" name="username" required></label><br> <label>メールアドレス:<input type="email" name="email" required></label><br> <label>パスワード:<input type="password" name="password" minlength="8" required></label><br> <button type="submit">登録</button> </form> <p>※ 空欄や不正な入力では送信できない</p>body { font-family: sans-serif; padding: 20px; } label { display: block; margin-bottom: 10px; } input { padding: 8px; border: 1px solid #ccc; border-radius: 4px; margin-left: 10px; } input:invalid { border-color: #dc3545; } button { background-color: #007bff; color: white; padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; }

Step 1: バリデーションとは何か

バリデーション とは、入力されたデータが 正しい形式かどうかを確認 することである。

バリデーションの重要性

バリデーションを行うことで:

  1. 不正なデータの送信を防ぐ
    • 空欄、形式違いのデータを受け付けない
  2. ユーザーに正しい入力方法を伝える
    • エラーメッセージで何が間違っているかを示す
  3. セキュリティを向上させる
    • 悪意のあるデータの入力を防ぐ

クライアント側(HTML5)とサーバー側(Springなど)の両方でバリデーションを行うのが基本である。

HTML5のバリデーション機能

HTML5では、属性を追加するだけで、ブラウザが自動的にバリデーションを行ってくれる。


Step 2: required(必須入力)

required属性 を付けると、その入力欄が 必須 になる。

<label for="username">ユーザー名:</label>
<input type="text" id="username" name="username" required>
  • 空欄のまま送信しようとすると、エラーメッセージが表示される
  • 「このフィールドを入力してください」のようなメッセージ

やってみよう:required属性を試す

以下のフォームで、ユーザー名を空欄のまま送信してみよう。エラーメッセージが表示される。

<form> <label for="username">ユーザー名(必須):</label> <input type="text" id="username" name="username" required><br><br> <label for="email">メールアドレス(必須):</label> <input type="email" id="email" name="email" required><br><br> <button type="submit">送信</button> </form> <p>※ 空欄で送信しようとするとエラーが表示される</p>input { padding: 8px; border: 2px solid #007bff; border-radius: 4px; width: 250px; } button { background-color: #28a745; color: white; padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; }

なぜrequiredが必要なのか?

必須項目を明示することで、ユーザーが入力漏れに気づきやすくなる。サーバー側でも必須チェックをするが、クライアント側で先にチェックすることでユーザー体験が向上する。

チェックボックスでrequiredを使う

<label>
<input type="checkbox" name="agree" required>
利用規約に同意する
</label>
  • チェックしないと送信できない

Step 3: minlength/maxlength(文字数制限)

minlength(最小文字数)

<label for="password">パスワード(8文字以上):</label>
<input type="password" id="password" name="password" minlength="8">
  • 8文字未満の場合、エラーメッセージが表示される

やってみよう:minlengthを試す

以下のパスワード入力欄に、8文字未満のパスワードを入力して送信してみよう。エラーメッセージが表示される。

<form> <label for="password">パスワード(8文字以上):</label> <input type="password" id="password" name="password" minlength="8" required><br><br> <button type="submit">送信</button> </form> <p>※ 8文字未満では送信できない</p>input { padding: 8px; border: 2px solid #dc3545; border-radius: 4px; width: 250px; } button { background-color: #007bff; color: white; padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; }

なぜminlengthが必要なのか?

パスワードが短すぎると、セキュリティが低下する。8文字以上などの最小文字数を設定することで、安全なパスワードを強制できる。


maxlength(最大文字数)

<label for="nickname">ニックネーム(20文字以内):</label>
<input type="text" id="nickname" name="nickname" maxlength="20">
  • 20文字を超えて入力できない(入力が制限される)

やってみよう:maxlengthを試す

以下のニックネーム入力欄に、20文字以上入力しようとしてみよう。20文字を超えて入力できないことを確認しよう。

<form> <label for="nickname">ニックネーム(20文字以内):</label> <input type="text" id="nickname" name="nickname" maxlength="20" placeholder="20文字まで"><br><br> <button type="submit">送信</button> </form> <p>※ 20文字を超えて入力できない</p>input { padding: 8px; border: 2px solid #ffc107; border-radius: 4px; width: 250px; } button { background-color: #007bff; color: white; padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; }

なぜmaxlengthを使うのか?

データベースに保存できる文字数には上限がある。また、長すぎる入力を防ぐことで、ユーザーインターフェースが崩れることを防げる。

両方を組み合わせる

<input type="password" minlength="8" maxlength="20" required>
  • 8文字以上20文字以内のパスワード
ポイント

maxlength入力を制限 するが、minlengthエラーを表示 する。

  • maxlength="20":20文字を超えて入力できない
  • minlength="8":8文字未満で送信しようとするとエラー

Step 4: min/max(数値範囲)

数値の範囲を指定

<label for="age">年齢(0〜120):</label>
<input type="number" id="age" name="age" min="0" max="120" required>
  • 0未満または120を超える数値を入力すると、エラーメッセージが表示される

やってみよう:min/maxを試す

以下の年齢入力欄に、0未満や120を超える数値を入力して送信してみよう。エラーメッセージが表示される。

<form> <label for="age">年齢(0〜120):</label> <input type="number" id="age" name="age" min="0" max="120" value="25" required><br><br> <button type="submit">送信</button> </form> <p>※ 0未満や120を超える値では送信できない</p>input { padding: 8px; border: 2px solid #17a2b8; border-radius: 4px; width: 100px; } button { background-color: #007bff; color: white; padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; }

なぜmin/maxが必要なのか?

年齢や個数など、妥当な範囲が決まっている数値には、min/maxを設定することで不正な入力を防げる。


日付の範囲を指定

<label for="birthday">生年月日:</label>
<input type="date" id="birthday" name="birthday" min="1900-01-01" max="2024-12-31">

やってみよう:日付の範囲を試す

以下の日付入力欄で、1900年1月1日から2024年12月31日の範囲内の日付を選んでみよう。

<form> <label for="birthday">生年月日:</label> <input type="date" id="birthday" name="birthday" min="1900-01-01" max="2024-12-31"><br><br> <button type="submit">送信</button> </form>input { padding: 8px; border: 2px solid #6c757d; border-radius: 4px; } button { background-color: #007bff; color: white; padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; }

Step 5: pattern(正規表現)

pattern属性 で、正規表現を使った複雑なバリデーションができる。

電話番号の形式チェック

<label for="phone">電話番号(ハイフンなし):</label>
<input type="tel" id="phone" name="phone" pattern="[0-9]{10,11}" required>
  • [0-9]{10,11}:0〜9の数字が10〜11桁

やってみよう:電話番号のpatternを試す

以下の電話番号入力欄に、10桁または11桁の数字を入力してみよう。それ以外の形式では送信できない。

<form> <label for="phone">電話番号(ハイフンなし、10-11桁):</label> <input type="tel" id="phone" name="phone" pattern="[0-9]{10,11}" placeholder="09012345678" required><br><br> <button type="submit">送信</button> </form> <p>※ 10桁または11桁の数字のみ受け付ける</p>input { padding: 8px; border: 2px solid #28a745; border-radius: 4px; width: 250px; } button { background-color: #007bff; color: white; padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; }

なぜpatternが必要なのか?

電話番号や郵便番号など、特定の形式が決まっている入力には、正規表現で厳密にチェックすることで不正な入力を防げる。


ユーザー名の形式チェック

<label for="username">ユーザー名(半角英数字のみ):</label>
<input type="text" id="username" name="username" pattern="[a-zA-Z0-9]+" required>
  • [a-zA-Z0-9]+:半角英数字が1文字以上

やってみよう:ユーザー名のpatternを試す

以下のユーザー名入力欄に、半角英数字以外の文字(ひらがな、記号など)を入力して送信してみよう。エラーが表示される。

<form> <label for="username">ユーザー名(半角英数字のみ):</label> <input type="text" id="username" name="username" pattern="[a-zA-Z0-9]+" placeholder="user123" required><br><br> <button type="submit">送信</button> </form> <p>※ 半角英数字以外は送信できない</p>input { padding: 8px; border: 2px solid #007bff; border-radius: 4px; width: 250px; } button { background-color: #007bff; color: white; padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; }

なぜ半角英数字のみに制限するのか?

ユーザー名がURLの一部になる場合、全角文字や記号が含まれるとエラーになることがある。半角英数字のみに制限することで、安全にシステムに登録できる。

よく使う正規表現パターン

用途パターン
半角数字のみ[0-9]+
半角英字のみ[a-zA-Z]+
半角英数字のみ[a-zA-Z0-9]+
電話番号(10-11桁)[0-9]{10,11}
郵便番号(ハイフンあり)[0-9]{3}-[0-9]{4}
重要

正規表現は複雑なので、最初は コピー&ペースト で使って構わない。

必要に応じて、正規表現の詳しい使い方を学ぶと良い。


Step 6: placeholder(入力例の表示)

placeholder属性 で、入力欄に ヒント を表示できる。

<label for="email">メールアドレス:</label>
<input type="email" id="email" name="email" placeholder="例:taro@example.com">
  • 入力欄が空の状態でヒントが表示される
  • ユーザーが入力を始めると、ヒントが消える

やってみよう:placeholderを確認する

以下の入力欄で、placeholderのヒントが表示されることを確認しよう。入力を始めるとヒントが消える。

<form> <label for="name">氏名:</label> <input type="text" id="name" name="name" placeholder="例:山田太郎"><br><br> <label for="email">メールアドレス:</label> <input type="email" id="email" name="email" placeholder="例:taro@example.com"><br><br> <label for="phone">電話番号:</label> <input type="tel" id="phone" name="phone" placeholder="例:09012345678"><br><br> <button type="submit">送信</button> </form>input { padding: 8px; border: 2px solid #6c757d; border-radius: 4px; width: 250px; } input::placeholder { color: #999; font-style: italic; } button { background-color: #007bff; color: white; padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; }

なぜplaceholderが有用なのか?

placeholderを使うことで、ユーザーがどのような形式で入力すれば良いかが一目でわかる。入力ミスを減らし、ユーザー体験が向上する。

使用例

<input type="text" name="name" placeholder="山田太郎">
<input type="tel" name="phone" placeholder="09012345678">
<input type="date" name="birthday" placeholder="1990-01-01">
ポイント

placeholderは あくまでヒント である。

必須事項や重要な説明は、<label>やテキストで明示すること。placeholderだけに頼らない。


Step 7: HTML5のバリデーションメッセージ

ブラウザが自動的に表示するエラーメッセージは、カスタマイズできる。

title属性でヒントを追加

<input type="password"
name="password"
minlength="8"
pattern="[a-zA-Z0-9]+"
title="8文字以上の半角英数字で入力してください"
required>
  • title属性に説明を書くと、エラー時に表示される

やってみよう:title属性を確認する

以下のパスワード入力欄に、不正な値を入力して送信してみよう。title属性に設定したメッセージが表示される。

<form> <label for="password">パスワード:</label> <input type="password" id="password" name="password" minlength="8" pattern="[a-zA-Z0-9]+" title="8文字以上の半角英数字で入力してください" required><br><br> <button type="submit">送信</button> </form> <p>※ 不正な値を入力すると、titleの内容が表示される</p>input { padding: 8px; border: 2px solid #dc3545; border-radius: 4px; width: 250px; } button { background-color: #007bff; color: white; padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; }

なぜtitle属性を使うのか?

デフォルトのエラーメッセージだけでは、ユーザーに何が間違っているか伝わりにくい。title属性で具体的な説明を加えることで、ユーザーが正しく入力できるようになる。

JavaScriptでカスタムメッセージ(参考)

const input = document.getElementById('password');
input.setCustomValidity('パスワードは8文字以上で入力してください');

(JavaScriptは本教材の範囲外だが、可能性として知っておくと良い)


演習

この章で学んだ内容を確認するため、以下の演習問題に取り組んでください。

演習問題は、docs/src/questions/frontend/form_validation/フォルダにあります:

  1. k1.mdx: バリデーションの必要性を説明できる
  2. w1.mdx: required属性で必須入力を指定できる
  3. w2.mdx: minlength/maxlengthで文字数制限を指定できる
  4. w3.mdx: min/maxで数値範囲を指定できる
  5. w4.mdx: pattern属性で正規表現バリデーションを指定できる
  6. w5.mdx: placeholder属性で入力例を表示できる

まとめ

この章では、 フォームとバリデーション について学んだ。

🎯 達成できたこと

  • ✅ バリデーションの必要性(不正なデータを防ぐ)を理解した
  • ✅ required属性で必須入力を指定できるようになった
  • ✅ minlength/maxlengthで文字数制限を指定できるようになった
  • ✅ min/maxで数値範囲を指定できるようになった
  • ✅ pattern属性で正規表現バリデーションを指定できるようになった
  • ✅ placeholder属性で入力例を表示できるようになった

📚 学んだ内容

  • HTML5のバリデーション属性を使うと、ブラウザが自動でチェックしてくれる
  • クライアント側とサーバー側の両方でバリデーションを行うのが基本
  • requiredで必須、minlength/maxlengthで文字数、min/maxで数値範囲を指定
  • patternで正規表現を使った複雑なバリデーションができる
  • placeholderは入力のヒントを表示する

🚀 次のステップ

次の章では、 Bootstrap入門 について学ぶ。 CSSフレームワークを使って、効率的に見栄えの良いデザインを作成する。


💡 よくある質問

Q1: HTML5のバリデーションだけで十分か?

A: 十分ではない。サーバー側でも必ずバリデーションを行うべきである。

理由:

  • HTML5のバリデーションは、ブラウザの機能を無効にすれば回避できる
  • 悪意のあるユーザーが、直接サーバーにデータを送信することもできる

ベストプラクティス:

  1. クライアント側(HTML5):ユーザーに即座にフィードバックを提供
  2. サーバー側(Spring):最終的な安全確認

両方を組み合わせることが重要である。

Q2: requiredとplaceholderを同時に使える?

A: できる:

<input type="text" name="name" placeholder="例:山田太郎" required>

placeholderはヒント、requiredは必須チェックである。

Q3: 正規表現が難しくてわからない

A: 最初は コピー&ペースト で使って構わない。

よく使うパターンを覚えておいて、必要に応じて調整すれば良い。

参考サイト:

  • Regex101(正規表現のテストツール)
  • MDN Web Docs(正規表現の説明)

Q4: エラーメッセージを日本語にできないのか?

A: ブラウザのデフォルトメッセージは、ブラウザの言語設定に依存する。

カスタマイズする場合は、JavaScriptを使う必要がある:

input.addEventListener('invalid', function() {
this.setCustomValidity('このフィールドは必須です');
});

Q5: type="email"だけで十分では?

A: type="email"は基本的なチェックのみである。

より厳密なチェックが必要な場合は、pattern属性を追加する:

<input type="email"
name="email"
pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$"
required>

Q6: バリデーションをスキップする方法は?

A: <form>タグにnovalidate属性を付ける:

<form action="/submit" method="POST" novalidate>
<!-- バリデーションがスキップされる -->
</form>

ただし、通常は使うべきではない。開発中のテスト用である。

Q7: type="number"でminとmaxを指定したのに、手入力で範囲外の値を入力できてしまう

A: これは仕様である。

min/max送信時にチェック されるが、 入力時には制限されない

送信しようとすると、エラーメッセージが表示される。