3日目のゴールと今日のテーマ
3日目は「バリデーションの質を上げる日」です。
昨日までで、あなたはすでに
- 入力中にエラーを動的に表示
- touched(触ったかどうか)による UX 改善
- 正規表現による基本チェック
を体験しました。
今日はここからさらに一歩進めて、
- エラーの種類を増やす(複数条件のバリデーション)
- エラーの優先順位を設計する(どのメッセージを出すか)
- フィールドごとの状態とフォーム全体の状態を整理する
- submit 制御をより堅牢にする
という「中級バリデーションの本質」に踏み込みます。
エラーの種類を増やす:複数条件をどう扱うか
バリデーションは「1つの条件」では終わらない
メールもパスワードも、実際には複数の条件があります。
メールなら:
- 空でない
- 形式が正しい
- 長すぎない(UX 的に追加してもよい)
パスワードなら:
- 空でない
- 長さが足りている
- 英字と数字を含む
- 記号を許可するかどうか
これらを「どの順番でチェックするか」が UX に直結します。
エラーの優先順位を決める(重要)
例えばパスワードが空のときに、
「英字と数字を含めてください」
と出たら、ユーザーは混乱します。
だから、バリデーション関数は「優先順位の高い条件から順にチェック」します。
function validatePassword(value) {
if (!value) {
return "パスワードを入力してください。";
}
if (value.length < 8) {
return "パスワードは8文字以上にしてください。";
}
if (!/[A-Za-z]/.test(value)) {
return "英字を1文字以上含めてください。";
}
if (!/\d/.test(value)) {
return "数字を1文字以上含めてください。";
}
return "";
}
JavaScriptここでの深掘りポイントは、
- 「最初に引っかかったエラーだけ返す」
- 複数のエラーを一度に出さない(UX が悪くなる)
という設計です。
エラー状態を「フィールド単位」で管理する
state の errors を整理する
昨日の state はこうでした。
errors: {
email: "",
password: "",
form: "",
}
JavaScript今日はこれを「フィールド単位で完結する」ように扱います。
- email のエラーは email のバリデーション関数だけが決める
- password のエラーは password のバリデーション関数だけが決める
- form のエラーは submit 時にだけ使う
この分離ができると、コードが一気に読みやすくなります。
touched と errors の関係を明確にする
UX 的に重要なのは、
- touched が false のときはエラーを表示しない
- touched が true のときは errors をそのまま表示する
というルールです。
render の中でこう書けます。
emailErrorEl.textContent =
state.touched.email ? state.errors.email : "";
passwordErrorEl.textContent =
state.touched.password ? state.errors.password : "";
JavaScriptこれにより、
- 初回は静か
- 一度触ったら、リアルタイムでエラー更新
という自然な UX になります。
入力中のバリデーションを「より自然に」する
input と blur の役割を再確認する
昨日はこうでした。
- blur → touched を true にする
- input → touched が true のときだけエラー更新
今日はこれを「より自然に」します。
例:メール欄の改善版
emailInputEl.addEventListener("input", () => {
state.email = emailInputEl.value;
if (state.touched.email) {
state.errors.email = validateEmail(state.email);
}
render();
});
emailInputEl.addEventListener("blur", () => {
state.touched.email = true;
state.errors.email = validateEmail(state.email);
render();
});
JavaScriptここでの UX のポイントは、
- 入力中にエラーが出るのは「一度触った後だけ」
- blur した瞬間に必ずエラーが出るので、ユーザーは気づきやすい
という点です。
パスワードも同じパターンで扱う
passwordInputEl.addEventListener("input", () => {
state.password = passwordInputEl.value;
if (state.touched.password) {
state.errors.password = validatePassword(state.password);
}
render();
});
passwordInputEl.addEventListener("blur", () => {
state.touched.password = true;
state.errors.password = validatePassword(state.password);
render();
});
JavaScriptsubmit 制御を「堅牢」にする
submit 時は「全フィールドを強制チェック」
入力中のバリデーションがあっても、submit 時には必ず全体をチェックします。
formEl.addEventListener("submit", (event) => {
event.preventDefault();
state.touched.email = true;
state.touched.password = true;
state.errors.email = validateEmail(state.email);
state.errors.password = validatePassword(state.password);
const hasError =
state.errors.email || state.errors.password;
if (hasError) {
state.errors.form = "入力内容を確認してください。";
if (state.errors.email) {
emailInputEl.focus();
} else if (state.errors.password) {
passwordInputEl.focus();
}
render();
return;
}
state.errors.form = "";
state.isSubmitting = true;
render();
setTimeout(() => {
state.isSubmitting = false;
state.errors.form = "ログイン成功!(ダミー)";
render();
}, 800);
});
JavaScriptここでの深掘りポイントは、
- submit 時は touched を強制的に true にする
- 最初のエラーにフォーカスを移す(UX の大事な要素)
- isSubmitting で連打を防ぐ
という「実務でよく使うパターン」を体験できることです。
3日目のまとめと、明日へのつなぎ
今日あなたが身につけたのは、まさに「中級バリデーションの核」です。
- 複数条件のバリデーションを優先順位付きで設計する
- エラー状態をフィールド単位で管理する
- touched を使って UX を自然にする
- submit 時に全体チェック+フォーカス移動
- バリデーション関数を純粋関数として設計する
明日(4日目)はここからさらに、
- バリデーションの再利用性を高める
- 複数フィールドを追加したときの設計の崩れにくさ
- エラー表示のコンポーネント化(関数化)
など、「設計力」をさらに伸ばす方向に進みます。
もし余裕があれば、今日のコードで
- メールを
aaa@bbbにして blur - パスワードを
abc123にして blur - submit を押してフォーカス移動を確認
など、実際に触って UX の違いを感じてみてください。


