メニューの絞り込み
中段 / 目安 25分
「メニューが8品まで増えたの」と陽葵さんは誇らしげですが、すぐ困り顔になりました。「そうしたら『ドリンクだけ見たい』っておっしゃるお客様がいて。カテゴリで絞り込めない?」
script.js には8品ぶんのデータが menu という配列で用意してあります。1件は name price category の3つを持つオブジェクトです。category に入るのは drink food sweets の3種類です。
HTML 側の #menu-list は空っぽの ul です。カテゴリのボタンにはそれぞれ data-category が付いていて、すべてを出すボタンだけ all になっています。
この問題の型は「データを絞って、描き直す」です。ひな形の render(category) の中で、表示する配列を選びます。ボタンが押されたら、押されたボタンのカテゴリでその関数を呼び直します。描き直すときは、前に描いたものを一度消してから並べ直してください。消さずに足すと、押すたびに増えていきます。
ページを開いた直後は8品すべてが並んでいる状態にします。
完成条件
- 開いた直後は8品すべてが
#menu-listに並ぶ - 1件は
class="menu-item"のliとして描く - 各件に商品名(
class="name")と価格(class="price")を入れる - カテゴリのボタンを押すと、そのカテゴリの品だけが並ぶ
- 「すべて」を押すと8品に戻る
進め方
配列から条件に合うものだけを取り出すのは filter です。関数は1件ずつ受け取り、残したいものなら true を返します。たとえば本の一覧なら次のように書けます。元の配列は変わりません。
JavaScript
const books = [{ title: "星の本", genre: "science" }, { title: "旅の本", genre: "travel" }];
const scienceBooks = books.filter(function (book) {
return book.genre === "science";
});=== は一致、!== は不一致を調べます。たとえば book.genre !== "travel" は「旅行以外の本か」という判定です。値を入れ直す変数には let を使います。let shelf = books; shelf = scienceBooks; なら、最初は全件、次は科学の本を指します。
今回の all は絞り込まない合図です。まず表示用の変数を元の配列にし、all 以外のときだけ選び直すと、条件を分けて考えられます。
描き直しの最初にやるのは list.innerHTML = "" です。これで前回ぶんが消えます。そのうえで、選んだ配列の forEach に補助関数 appendMenuItem を渡します。この関数は1件を受け取り、名前と価格の入った li を作って一覧へ追加します。要素を作る処理は書き直さなくてかまいません。関数を渡す書き方は、たとえば function printTitle(book) { console.log(book.title); } を用意して books.forEach(printTitle); とする形です。呼び出すための () は付けません。
押されたボタンのカテゴリは、そのボタンの dataset.category から読めます。たとえば <button data-genre="travel">旅行</button> なら button.dataset.genre は "travel" です。今回のボタン登録と初回の render("all") はひな形にあります。編集するのは render の中だけです。
ヒントは3段階で、①方針、②使う構文、③部分解の順に出ます。1つも開けずに通せたら、その問題は自分のものです。
課題
- 編集するのは render(category) の中だけ。menu と appendMenuItem(item) は用意済み
- 開いた直後と「すべて」を押したときは8品を表示する
- 他のカテゴリでは menu.filter で一致する品だけを選ぶ
- 前の一覧を消し、選んだ配列の forEach で appendMenuItem を呼ぶ
- 商品名と価格を含む li.menu-item の作成と、ボタン登録は補助コードに任せる
ヒント
前のヒントを開くと次が開きます。開かずに解けると未開封クリアです