JavaScript | 1 日 90 分 × 7 日アプリ学習:フォーム送信シミュレーター(初級編)

JavaScript
スポンサーリンク

5日目のゴールと今日やること

5日目のテーマは
「フォーム送信シミュレーターを“より整理された、拡張しやすいアプリ”に進化させる」
ことです。

ここまでの 1〜4日目であなたは、

  • submit の制御
  • preventDefault の本質
  • 入力 → 確認 → 完了 の基本フロー
  • バリデーション(空欄・メール形式)
  • ラジオ・チェックボックス・セレクトの扱い
  • 擬似送信中アニメーション

ここまで理解できています。

5日目はここに、

  • 入力項目を「自動で収集」する
  • 確認画面を「ループで自動生成」する
  • formData を「動的に作る」
  • コードを関数化して読みやすくする

という、“アプリとしての設計力”を加えていきます。


入力項目を「自動で収集する」仕組みを作る

これまでの問題点

4日目までのコードは、
入力項目が増えるたびにこう書いていました。

formData.name = document.getElementById("nameInput").value;
formData.email = document.getElementById("emailInput").value;
formData.message = document.getElementById("messageInput").value;
JavaScript

項目が 3 つならまだ良いですが、
10 個、20 個になると管理が大変です。

解決策:入力項目を「まとめて取得」する

フォーム内の input / textarea / select を
すべて取得してループで処理します。

const inputs = form.querySelectorAll("input, textarea, select");

inputs.forEach(input => {
  const key = input.name;
  if (!key) return;

  if (input.type === "checkbox") {
    if (!formData[key]) formData[key] = [];
    if (input.checked) formData[key].push(input.value);
  } else if (input.type === "radio") {
    if (input.checked) formData[key] = input.value;
  } else {
    formData[key] = input.value.trim();
  }
});
JavaScript

深掘り:name 属性が“データのキー”になる

HTML の input には name 属性があります。

<input name="email">

この name が
formData のキー(email)になる
という仕組みは、実際のフォームアプリでも必ず使われます。


確認画面を「ループで自動生成」する

これまでの問題点

確認画面をこう書いていました。

confirmList.innerHTML = `
  <p>名前:${formData.name}</p>
  <p>メール:${formData.email}</p>
`;
JavaScript

項目が増えると、
この部分もどんどん増えていきます。

解決策:formData をループして自動生成する

let html = "";

for (const key in formData) {
  const value = Array.isArray(formData[key])
    ? formData[key].join("、")
    : formData[key];

  html += `<p>${key}${value}</p>`;
}

confirmList.innerHTML = html;
JavaScript

深掘り:ループ生成は「項目が増えても壊れない」

  • 入力項目を追加
  • name を付ける
  • formData に自動で入る
  • 確認画面も自動で増える

この仕組みは、
大規模フォームでも使える設計です。


formData を「動的に作る」仕組みを完成させる

formData を空オブジェクトで用意する

let formData = {};
JavaScript

submit 時に中身を作ります。

formData = {}; // 初期化

inputs.forEach(input => {
  const key = input.name;
  if (!key) return;

  if (input.type === "checkbox") {
    if (!formData[key]) formData[key] = [];
    if (input.checked) formData[key].push(input.value);
  } else if (input.type === "radio") {
    if (input.checked) formData[key] = input.value;
  } else {
    formData[key] = input.value.trim();
  }
});
JavaScript

深掘り:動的生成は「拡張性の核」

  • 項目が増えても formData のコードを変えない
  • 確認画面も自動で増える
  • バリデーションもループで書ける

アプリが大きくなるほど、この設計が効いてきます。


コードを「関数化」して読みやすくする

入力収集を関数にする

function collectFormData() {
  const data = {};
  const inputs = form.querySelectorAll("input, textarea, select");

  inputs.forEach(input => {
    const key = input.name;
    if (!key) return;

    if (input.type === "checkbox") {
      if (!data[key]) data[key] = [];
      if (input.checked) data[key].push(input.value);
    } else if (input.type === "radio") {
      if (input.checked) data[key] = input.value;
    } else {
      data[key] = input.value.trim();
    }
  });

  return data;
}
JavaScript

確認画面生成も関数にする

function renderConfirmScreen(data) {
  let html = "";
  for (const key in data) {
    const value = Array.isArray(data[key])
      ? data[key].join("、")
      : data[key];
    html += `<p>${key}${value}</p>`;
  }
  confirmList.innerHTML = html;
}
JavaScript

深掘り:関数化は「責務を分ける」こと

  • collectFormData → 入力を集める
  • renderConfirmScreen → 確認画面を作る
  • submit → フローを管理する

このように責務を分けると、
コードが壊れにくく、読みやすくなります。


5日目の完成コード(動的収集+自動生成+関数化)

JavaScript

const form = document.getElementById("inputForm");
const confirmScreen = document.getElementById("confirmScreen");
const completeScreen = document.getElementById("completeScreen");
const loadingScreen = document.getElementById("loadingScreen");
const confirmList = document.getElementById("confirmList");
const errorMessage = document.getElementById("errorMessage");

let formData = {};

function collectFormData() {
  const data = {};
  const inputs = form.querySelectorAll("input, textarea, select");

  inputs.forEach(input => {
    const key = input.name;
    if (!key) return;

    if (input.type === "checkbox") {
      if (!data[key]) data[key] = [];
      if (input.checked) data[key].push(input.value);
    } else if (input.type === "radio") {
      if (input.checked) data[key] = input.value;
    } else {
      data[key] = input.value.trim();
    }
  });

  return data;
}

function renderConfirmScreen(data) {
  let html = "";
  for (const key in data) {
    const value = Array.isArray(data[key])
      ? data[key].join("、")
      : data[key];
    html += `<p>${key}${value}</p>`;
  }
  confirmList.innerHTML = html;
}

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

  formData = collectFormData();

  if (!formData.name) {
    errorMessage.textContent = "名前を入力してください。";
    return;
  }

  if (!formData.email) {
    errorMessage.textContent = "メールを入力してください。";
    return;
  }

  errorMessage.textContent = "";

  renderConfirmScreen(formData);

  form.style.display = "none";
  confirmScreen.style.display = "block";
});

document.getElementById("backButton").addEventListener("click", () => {
  confirmScreen.style.display = "none";
  form.style.display = "block";
});

document.getElementById("sendButton").addEventListener("click", () => {
  confirmScreen.style.display = "none";
  loadingScreen.style.display = "block";

  setTimeout(() => {
    loadingScreen.style.display = "none";
    completeScreen.style.display = "block";
  }, 1500);
});
JavaScript

今日いちばん深く理解してほしいこと

フォームアプリは「データ収集 × 自動生成 × 関数化」で強くなる

5日目であなたが身につけたのは、

  • 入力項目を自動で集める
  • 確認画面を自動で作る
  • formData を動的に生成する
  • 関数化で責務を分ける

という、
本格的なフォームアプリの設計そのものです。

この仕組みを理解すると、
どんなフォームでも作れるようになります。


6日目へのつなぎ

6日目からは、

  • バリデーションを関数化して再利用可能にする
  • 入力エラーを項目ごとに表示する
  • 完了画面をもっとアプリらしく演出する
  • formData を JSON として保存する

という、“実用アプリの仕上げ”に進みます。

今日の内容を理解できたあなたなら、
もうフォームアプリの中級者として胸を張っていいレベルです。

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