JavaScript | 1 日 90 分 × 7 日アプリ学習:入力チェックアプリ(初級編)

JavaScript
スポンサーリンク

7日目のゴールと今日のテーマ

7日目のテーマは、
「入力チェックアプリでやってきたことを“設計レベル”で整理して、自分の言葉で説明できるようになること」です。

新しい機能を増やす日ではありません。
ここまでやってきた、

空チェック
条件分岐
エラー表示
未入力警告
文字数制限

を、「バラバラのテクニック」ではなく「一つのアプリの設計」としてつなげ直す日です。

今日のゴールはこうです。

入力チェックの流れを、自分の言葉で説明できる。
空チェック/文字数制限/追加ルールが、どう組み合わさっているか理解できる。
「こういう入力フォームなら自分で組めそう」と思える。

ここまで来たら、初級・入力チェックアプリはしっかり卒業です。


ここまでで作ってきた“入力チェックの型”を振り返る

入力チェックの大きな流れ

あなたが作ってきたのは、こんな流れです。

  1. ユーザーがフォームに入力する(名前・コメント など)。
  2. ボタン(送信)を押すと、JavaScript が値を読み取る。
  3. 値を validate に渡して、
    「未入力か」「短すぎないか」「長すぎないか」「(必要なら)文字の種類はOKか」をチェックする。
  4. NGならエラーメッセージを返す。
  5. エラーメッセージを、項目ごと・フォーム全体に表示する。
  6. エラーが1つもなければ「送信完了」として処理を進める。

この流れを、ずっと丁寧に育ててきました。


validate の「中身」と「役割」を言葉で整理する

validate は「チェック係」

最終形に近い validate は、だいたいこんな形でした。

function validate(text, minLength, maxLength, options = {}) {
  const trimmed = text.trim();

  if (trimmed === "") {
    return "未入力です。";
  }

  if (trimmed.length < minLength) {
    return minLength + "文字以上で入力してください。";
  }

  if (trimmed.length > maxLength) {
    return maxLength + "文字以内で入力してください。";
  }

  if (options.hiraganaOnly) {
    const regex = /^[ぁ-ん]+$/;
    if (!regex.test(trimmed)) {
      return "ひらがなのみで入力してください。";
    }
  }

  return "";
}
JavaScript

ここでやっていることを、日本語で分解するとこうです。

  1. 前後の空白を削る(trim)。
  2. 何も残っていなければ「未入力」としてエラー。
  3. 最短文字数より短ければ「短すぎ」としてエラー。
  4. 最長文字数より長ければ「長すぎ」としてエラー。
  5. hiraganaOnly オプションが true のときだけ、「ひらがなだけか?」を正規表現でチェック。
  6. どれにもひっかからなければ、エラーなし(空文字)を返す。

重要なのは、「表示はしない」 ことです。
この関数はあくまで「チェックしてメッセージを返すだけ」。
「どこにどう表示するか」は別の担当(関数)が受け持っています。


項目ごとのチェックをどう組み合わせていたか

名前とコメントの例

フォームには、こういう項目がありました。

名前
コメント

それぞれに、違うルールを持たせていました。

const minNameLength = 2;
const maxNameLength = 20;
const minCommentLength = 10;
const maxCommentLength = 200;
JavaScript

チェックするときはこうでした。

const nameError = validate(nameValue, minNameLength, maxNameLength, { hiraganaOnly: true });
const commentError = validate(commentValue, minCommentLength, maxCommentLength);
JavaScript

ここでの設計のポイントは、

名前 → 「2〜20文字」+「ひらがなのみ」
コメント → 「10〜200文字」+「文字種は自由」

という「違うルール」を、
同じ validate 関数で扱えていることです。

違うのは「渡す設定」だけ。
チェックの流れそのものは、共通です。


エラー状態を「オブジェクト」としてまとめる意味

errors オブジェクト

エラーを、「ただの変数の集まり」ではなく「1つの状態」として扱っていました。

const errors = {
  name: nameError,
  comment: commentError,
};
JavaScript

この状態をもとに、

showError(nameErrorEl, errors.name);
showError(commentErrorEl, errors.comment);
JavaScript

と表示し、

function hasErrors(errors) {
  return errors.name !== "" || errors.comment !== "";
}
JavaScript

で「フォーム全体としてOKかどうか」を判断していました。

この構造の良さは、

エラーが増えても、“errorsを見れば今の状態が一望できる”ことです。

たとえば将来、メールアドレス欄を足すなら、

const errors = {
  name: ...,
  comment: ...,
  email: ...,
};
JavaScript

に増やして、hasErrors の中で errors.email も見るだけです。


エラー表示の役割分担:項目 / 全体 / 入力中

項目ごとのエラー表示

項目ごとには、こうしていました。

function showError(el, message) {
  el.textContent = message;
}
JavaScript

名前のエラーは nameErrorEl
コメントのエラーは commentErrorEl

というように、
「どこに出すか」は showError の引数で渡していました。

全体エラー

フォーム全体には、こういうメッセージも用意しました。

function showFormError(message) {
  formErrorEl.textContent = message;
}
JavaScript

hasErrors(errors)true のときだけ、例えば

showFormError("入力内容に誤りがあります。各項目のエラーをご確認ください。");
JavaScript

のように出す。

これによって、

「どこがダメか」 → 項目エラー
「フォーム全体はOKか」 → 全体エラー

という2つのレベルで、ユーザーに状態を伝えられるようになっていました。

入力中の挙動

入力し始めたときには、

nameInputEl.addEventListener("input", () => {
  showError(nameErrorEl, "");
  showFormError("");
});
JavaScript

のように、

・その項目のエラー
・フォーム全体のエラー

を一旦消すことで、

「今なおしてるよね、じゃあいったんエラーは引っ込めておくね」

という振る舞いにしていました。


条件分岐の“設計”として見たときに大事なこと

1. 条件の順番には意味がある

validate 内の if の順番、覚えていますか?

空チェック
短すぎチェック
長すぎチェック
(オプションで)文字種チェック

この順番は、「直しやすさ」「理解しやすさ」を意識して決めていました。

何も書いてない → まず書いて。
少なすぎる → もう少し書いて。
多すぎる → 少し削って。
文字の種類が違う → 内容の質を変えて。

条件はどの順番でも“動く”かもしれないけれど、
「どうエラーが出るか」「ユーザーがどう感じるか」を考えて順番を設計していました。

2. 1つの if には1つの意味だけ

if (trimmed === "") { ... }
if (trimmed.length < minLength) { ... }
if (trimmed.length > maxLength) { ... }
JavaScript

のように、

1つの if で、
1つのルールだけを見る。

これを崩して、

if (trimmed === "" || trimmed.length < minLength) { ... }
JavaScript

みたいにすると、

「どっちでエラーになったのか」が分かりにくくなります。

「条件1つ=if 1つ」
このシンプルさが、読みやすさを作っていました。


7日目のミニワーク:自分の言葉で“設計”を説明してみる

ここから少し、あなた自身に問いかける形で整理してみます。

質問①:

「この入力チェックアプリは、どんな順番で入力をふるいにかけていますか?」

空 → 長さの下限 → 長さの上限 → (オプションで)文字種

この流れを、自分の言葉で説明してみてください。

質問②:

「エラーはどこで決まり、どこで表示されていますか?」

チェックは validate
表示は showError / showFormError
全体のOK/NG判定は hasErrors

この“役割分担”を、自分の言葉で整理してみてください。

質問③:

「新しく項目を増やすとしたら、どこを触りますか?」

例えば「メールアドレス」欄を足すとしたら、

HTMLに input + error を追加。
JavaScriptで要素を取得。
メール用の validate 呼び出しを handleSubmit に追加。
errors.email を作り、hasErrors と表示処理に組み込む。
(必要なら)validate 自体を、メール用のオプションに対応させる。

こういう流れがイメージできたら、もう“設計できている側”です。


7日目のまとめと、これからの一歩

7日目は、「新しい文法を覚える日」ではありませんでした。

あなたがこの7日間で身につけたのは、こういう感覚です。

入力を受け取る位置と、チェックする位置と、表示する位置を分けて考える。
空チェック・文字数制限・文字種チェックなどのルールを、validate という一つの箱にまとめる。
エラー状態をオブジェクト(errors)として持ち、フォーム全体のOK/NGを hasErrors で判断する。
ユーザーがどう直すかをイメージしながら、エラーの順番やメッセージの言い方を設計する。

これはもう、「ただ書ける」ではなく
「入力フォームを設計できる」側の感覚 です。

最後に、あえてひとつだけ聞きたい。

この7日間で作ってきた入力チェックの型を、
もし自分の生活や仕事に持ち込むなら、どこに使ってみたいですか?

・自分用のメモアプリの「タイトル必須チェック」
・日記の「一言コメントは10文字以上」
・簡単な「お問い合わせフォーム」

どんな小さなものでもいいです。
「ここなら使えそう」と思えた瞬間、その入力チェックは“練習用のサンプル”から“あなたの道具”に変わります。

その場所を一つ、心の中で決めてみてください。
そこから先は、もうあなたのアプリの番です。

タイトルとURLをコピーしました