【もりけん塾】JavaScript課題22 -Vanilla JSでテーブルを実装③ (ソート機能を複数にする)-

JavaScript

Vanilla JSを使用して、JSONデータをもとにテーブルを実装をしています。今回はソート機能を複数にする課題に挑戦しました。

こんにちは。Webコーダーのはるです。

現在、所属している「もりけん塾」でハンズオン課題 に取り組み、レビューをいただいています。

今日は、課題22 についてアウトプットをしていきます。
(前回までのアウトプットは、こちらです。)

実装する過程で学んだことを、学習ノートとして記録していきます。

認識の間違えている箇所がありましたら、お問い合わせからご指摘いただけるとうれしいです。

Vanilla JSでテーブルを実装③

今回、取り組んだ課題はこちらです。

課題20-21で作成したテーブル + ソート1つに、ソートをもう一つ追加していきます。

(もりけん先生のJavaScriptハンズオン課題より)

前回までの課題はこちらです。

作成したJSONデータ

こちらにまとめています。

ソートボタンを複数箇所に設置

まず、設置したいカラム名を配列に収めます。今回は、IDと年齢でソートができるようにします。

const sortTarget = [tableTitlesData.userId, tableTitlesData.age];

※tableTitlesDataは、JSONから取得したデータのキーと、実際のカラム名をオブジェクトで管理したものです。

const tableTitlesData = {
 "userId": "ID",
 "name": "名前",
 "gender": "性別",
 "age": "年齢"
}

sortTargetが存在していれば、それぞれの<th>をfind()で検索して、is-targetクラスを付与 & createSortButton()でソートボタンを設置します。

const renderSortButton = () => {
 const sortTarget = [tableTitlesData.userId, tableTitlesData.age];

 if(sortTarget) {
  sortTarget.forEach(target => {
   const targetEl = [...document.querySelectorAll(".js-table-title")].find(el => el.textContent === target);
   targetEl.classList.add("is-target");
   targetEl.insertAdjacentElement('beforeend', createSortButtons());
  })
 }
};

※createSortButton()については前回触れたので割愛します。

クリックイベント

前回作成したクリックイベントを、ボタンが複数になっても機能するように修正しました。

/* 修正後 */
const addEventListenerForSortButtons = data => {
 const sortButtons = [...document.querySelectorAll(".is-target")]; //追加

 sortButtons.forEach(sortButton => {
  sortButton.addEventListener("click", (e) => {
   const activeColumn = e.currentTarget; //追加

   initSortButtonStatus(activeColumn);
   switchSortButtons(activeColumn);

   const trArray = [...document.querySelectorAll(".js-table-row")];
   const sortData = createSortingData(data, activeColumn);

   trArray.forEach((tr, index) => {
    const tdItems = tr.children;
    changeTableContents(tdItems, sortData[index]);
   })
  });
 })
};

sortButtonsはis-targetクラスのついた<th>を配列にしたものです。

sortButtonsに対してforEachでクリックイベントを設定しました。

addEventListener内では、最初にクリックされたカラムを探します。

const activeColumn = e.currentTarget; //追加

このカラム(<th>)を、関数の引数にそれぞれ渡すことで、押したボタンによってソートを切り替えることができます。

initSortButtonStatus(activeColumn);
switchSortButtons(activeColumn);

const trArray = [...document.querySelectorAll(".js-table-row")];
const sortData = createSortingData(data, activeColumn);

※initSortButtonStatus(後述)は、片方のボタンを押した後に、もう片方のボタンを押したら、最初のボタンがデフォルトに戻るリセット機能です。

※switchSortButtonsは、ボタンの状態をdefault → asc → desc に 切り替える機能です。前回触れたので割愛します。

※createSortingDataは、ソートをしたデータを返します。こちらも割愛します。

ボタンの初期化

先述のとおり、片方のボタンを押した後に、もう片方のボタンを押したら、最初のボタンがデフォルトに戻るリセット機能を作成しました。

const initSortButtonStatus = (target) => {
 const noTargetColumn = [...document.querySelectorAll(".is-target")].filter(column => column !== target);
 noTargetColumn.forEach(column => {
  column.querySelector(".is-active").classList.remove("is-active");
  column.querySelector("[data-button-status='default']").classList.add("is-active");
 })
}

まず、今選択されていないカラムを検索します。is-targetクラスがついているカラム(ソートボタンが実装されているカラム)で、今targetではないものをfilter()しました。

const noTargetColumn = [...document.querySelectorAll(".is-target")].filter(column => column !== target);

使われていないカラムのソートボタンをdefalutに戻します。

noTargetColumn.forEach(column => {
  column.querySelector(".is-active").classList.remove("is-active");
  column.querySelector("[data-button-status='default']").classList.add("is-active");
})

その他 学んだこと

レビューで、絶対に覆らない固定的な値は、objectで管理するものだと教わりました。

今回は、ソートボタンの状態をobjectで管理して、ソートボタンの状態をコード内で使用したいときは、objectを参照するように修正しました。

const Sort = {
 Default: "default",
 Asc: "asc",
 Desc: "desc",
}

今回のコード

//
学習に使用している本は、もりけん先生推奨の”JavaScript本格入門”です。

あとがき

さえさん(@sae_prog)、もなかさん(@ruby443n)レビューいただきありがとうございました!

片方のボタンを押した後に、もう片方のボタンを押したら、最初のボタンがデフォルトに戻るリセット機能を仕様から汲み取れずレビューで指摘をいただきました・・!考えが浅かったです🙇‍♀️

しかし、課題20-21からソート機能は2つ以上になった時を想定していたので、いつもよりすんなり実装をすることができました。少し前進している…?!

お時間を割いていただきありがとうございました!

今日は以上です。

//

【もりけん塾で勉強しています】

もりけん先生(@terrace_tec)のHPはこちら

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