5日目のゴールと今日やること
5日目のテーマは
「ミニ総合アプリを“複数項目 × 条件分岐で切り替えられるアプリ”に進化させる」
ことです。
ここまでであなたは、
テキスト 1 項目を入力して、一覧表示・削除・編集・検索・ソート・バリデーションまで扱えるようになりました。
5日目はここに、
- 入力項目を「複数」にする(タイトル+カテゴリ+完了フラグなど)
- 一覧で「複数項目」を表示する
- 条件分岐で「表示モード」を切り替える(すべて/未完了のみ など)
- データ構造(オブジェクト)を意識して設計する
という、“ちょっとした ToDo アプリ”に近い形を目指します。
入力項目を「タイトル+カテゴリ」に増やす
HTML に複数入力欄を用意する
まずは、タイトルとカテゴリを入力できるようにします。
<div>
<input type="text" id="titleInput" placeholder="タイトルを入力">
<select id="categorySelect">
<option value="仕事">仕事</option>
<option value="プライベート">プライベート</option>
<option value="その他">その他</option>
</select>
<button id="addButton">追加</button>
</div>
<div id="errorArea"></div>
<div id="statusArea"></div>
<div id="listArea"></div>
ここでのポイントは、
「1件のデータが“複数の情報”を持つ前提で設計する」
という意識を持つことです。
データ構造をオブジェクトで設計する
1件のデータをこういう形にします。
{
id: 1,
title: "資料作成",
category: "仕事",
done: false
}
JavaScriptタイトル
カテゴリ
完了フラグ(done)
この 3 つを持つことで、
後で「カテゴリで絞り込み」「完了だけ表示」などの条件分岐がしやすくなります。
入力から「複数項目のオブジェクト」を作る
データ配列と ID カウンタ
let nextId = 1;
const items = [];
JavaScript入力値を取得してオブジェクトを作る
const titleInput = document.getElementById("titleInput");
const categorySelect = document.getElementById("categorySelect");
const addButton = document.getElementById("addButton");
addButton.addEventListener("click", () => {
const title = titleInput.value.trim();
const category = categorySelect.value;
const errors = validateInput(title);
if (errors.length > 0) {
showErrorMessages(errors);
return;
}
clearErrorMessages();
const newItem = {
id: nextId,
title: title,
category: category,
done: false
};
items.push(newItem);
nextId += 1;
titleInput.value = "";
renderList();
updateStatusMessage();
});
JavaScriptここで重要なのは、
「入力 → オブジェクト化 → 配列に push」
という流れを、
1件の“レコード”として意識することです。
バリデーションを「タイトル専用」にして整理する
タイトルのバリデーション関数
function validateInput(title) {
const errors = [];
if (title.length === 0) {
errors.push("タイトルを入力してください。");
}
if (title.length > 30) {
errors.push("タイトルは30文字以内にしてください。");
}
return errors;
}
JavaScriptエラー表示関数
const errorArea = document.getElementById("errorArea");
function showErrorMessages(errors) {
errorArea.innerHTML = "";
errors.forEach((msg) => {
const p = document.createElement("p");
p.textContent = msg;
p.style.color = "red";
errorArea.appendChild(p);
});
}
function clearErrorMessages() {
errorArea.innerHTML = "";
}
JavaScriptここでの深掘りポイントは、
「入力チェックは“入力の意味”に合わせて関数を分ける」
ということです。
タイトルのルール
(文字数・空チェックなど)
メールアドレスのルール
(@ を含むかなど)
こうやって“意味ごと”に関数を分けていくと、
アプリが大きくなっても整理しやすくなります。
一覧に「タイトル+カテゴリ+完了状態」を表示する
renderList を複数項目対応にする
const listArea = document.getElementById("listArea");
function renderList() {
listArea.innerHTML = "";
if (items.length === 0) {
const p = document.createElement("p");
p.textContent = "データがありません。";
listArea.appendChild(p);
return;
}
items.forEach((item) => {
const row = document.createElement("div");
const titleSpan = document.createElement("span");
titleSpan.textContent = item.title;
const categorySpan = document.createElement("span");
categorySpan.textContent = `(${item.category})`;
categorySpan.style.marginLeft = "8px";
categorySpan.style.fontSize = "0.9em";
categorySpan.style.color = "#555";
if (item.done) {
titleSpan.style.textDecoration = "line-through";
titleSpan.style.color = "#888";
}
const doneButton = document.createElement("button");
doneButton.textContent = item.done ? "未完了に戻す" : "完了";
doneButton.addEventListener("click", () => {
toggleDone(item.id);
});
const deleteButton = document.createElement("button");
deleteButton.textContent = "削除";
deleteButton.addEventListener("click", () => {
deleteItem(item.id);
});
row.appendChild(titleSpan);
row.appendChild(categorySpan);
row.appendChild(doneButton);
row.appendChild(deleteButton);
listArea.appendChild(row);
});
}
JavaScriptここでの重要ポイントは、
- 表示用の要素を「役割ごと」に分けて作る(タイトル用、カテゴリ用、ボタン用)
- done フラグによって見た目を変える(取り消し線・色)
というところです。
完了フラグを切り替える条件分岐
完了状態のトグル関数
function toggleDone(id) {
const target = items.find((item) => item.id === id);
if (!target) return;
target.done = !target.done;
renderList();
updateStatusMessage();
}
JavaScripttarget.done = !target.done; は、
true → false
false → true
と反転させる書き方です。
ここでの条件分岐は、
「今の状態によって次の状態を変える」
という典型的なパターンです。
削除機能を複数項目版でもそのまま使う
削除関数
function deleteItem(id) {
const newItems = items.filter((item) => item.id !== id);
items.length = 0;
newItems.forEach((i) => items.push(i));
renderList();
updateStatusMessage();
}
JavaScriptここは 2〜4日目と同じ考え方です。
- filter で「残したいものだけ」を残す
- 元の配列を書き換える
- 再描画する
という流れは、
「配列が真実、画面はその写し」という設計のままです。
条件分岐で「表示モード」を切り替える
表示モードの状態を持つ
「すべて」「未完了のみ」「完了のみ」
といった表示モードを切り替えられるようにします。
let viewMode = "all"; // "all" | "todo" | "done"
JavaScriptHTML にボタンを用意します。
<button id="viewAllButton">すべて</button>
<button id="viewTodoButton">未完了のみ</button>
<button id="viewDoneButton">完了のみ</button>
JavaScript で取得してイベントを付けます。
const viewAllButton = document.getElementById("viewAllButton");
const viewTodoButton = document.getElementById("viewTodoButton");
const viewDoneButton = document.getElementById("viewDoneButton");
viewAllButton.addEventListener("click", () => {
viewMode = "all";
renderList();
updateStatusMessage();
});
viewTodoButton.addEventListener("click", () => {
viewMode = "todo";
renderList();
updateStatusMessage();
});
viewDoneButton.addEventListener("click", () => {
viewMode = "done";
renderList();
updateStatusMessage();
});
JavaScriptviewMode に応じて表示するデータを絞る
renderList の中で、
viewMode に応じて items を絞り込みます。
function renderList() {
listArea.innerHTML = "";
let visibleItems = items;
if (viewMode === "todo") {
visibleItems = items.filter((item) => !item.done);
} else if (viewMode === "done") {
visibleItems = items.filter((item) => item.done);
}
if (visibleItems.length === 0) {
const p = document.createElement("p");
p.textContent = "表示できるデータがありません。";
listArea.appendChild(p);
return;
}
visibleItems.forEach((item) => {
// さきほどの row 作成処理をここで使う
});
}
JavaScriptここでの深掘りポイントは、
「状態(viewMode)× 条件分岐(if / else if)× filter」
という組み合わせです。
これができると、
「同じデータを、違う切り口で見せる」
というアプリらしい動きが作れます。
状態メッセージで「今どんな表示か」を伝える
状態メッセージの更新
const statusArea = document.getElementById("statusArea");
function updateStatusMessage() {
if (items.length === 0) {
statusArea.textContent = "まだデータがありません。タイトルとカテゴリを入力して追加してみましょう。";
return;
}
if (viewMode === "all") {
statusArea.textContent = "すべての項目を表示中です。完了ボタンで状態を切り替えられます。";
} else if (viewMode === "todo") {
statusArea.textContent = "未完了の項目だけを表示中です。";
} else if (viewMode === "done") {
statusArea.textContent = "完了した項目だけを表示中です。";
}
}
JavaScript状態(items の件数、viewMode)を見て、
メッセージを切り替えることで、
ユーザーが「今どういう状態なのか」を理解しやすくなります。
今日いちばん深く理解してほしいこと
1件のデータを
「複数のプロパティを持つオブジェクト」
として扱うことで、
- タイトル
- カテゴリ
- 完了フラグ
といった情報をまとめて管理できるようになりました。
そして、
- viewMode(表示モード)
- done(完了状態)
といった「状態」を
条件分岐と filter で組み合わせることで、
「同じデータを、違う視点で見せるアプリ」
になりました。
入力
一覧
削除
条件分岐
これらが、
「オブジェクト × 配列 × 状態 × 条件分岐」
という一本の軸でつながってきたのが、
今日の一番大きなポイントです。
明日 6日目・7日目では、
このミニ総合アプリを
「自分で説明できる」「自分なりにアレンジできる」
レベルまで仕上げていきます。

