【JavaScript入門】タスクを削除しよう

本章では、ToDoリストのタスクを削除する機能を実装します。

ToDoリストのタスクを削除させるには、削除するタスクを指定してDOMツリーから削除します。

ToDoリストのタスク削除機能を作ってみよう!

サンプルコードをダウンロードしよう

次のリンクから、サンプルコードをダウンロードしてください。

参考 ToDoアプリサンプルコードJavaScript入門

サンプルコードをテキストエディタで開いてみよう

「Visual Studio Code」から、先ほどダウンロードしたファイルから「タスクを削除しよう」を選択して開いてみましょう。

開くと次のような画面になります。

サンプルコードをChromeで開いてみよう

サンプルコードの「スタート」の「index.html」をChromeで開いてみましょう。

ページには「入力欄」と「全てのタスクを削除」というボタンが設置されています。

リストの右に「ゴミ箱のアイコン」があります。

このアイコンをクリックしたらタスクが削除されるように実装してみましょう。

ToDoタスクを削除する

まず、ToDoリストからタスクを削除するためのステップを見てみましょう。

ToDoアプリでは、ユーザーは次のような操作をしてタスクを削除します。

  1. タスクの削除ボタンを押下する
  2. リストからタスクが削除される

この一連の流れをコードで実装する必要があります。

コードで実装すると次のようなステップになります。

  1. 削除ボタンが押下されたときのイベントハンドラを設定する
  2. 削除されるタスクを取得する
  3. タスクをリストから削除する

では、一つずつ見てみましょう。

削除ボタンが押下されたときのイベントハンドラを設定する

まずは、削除ボタンが押下されたときのイベントハンドラを設定しましょう。

ここでの削除ボタンは「ゴミ箱のアイコン」です。

サンプルコードの「スタート」の「index.html」を開いてみましょう。

削除ボタン」と記述がされています。

<!-- 削除ボタン -->
<td class="right-align">
  <a class="btn-floating btn-small waves-effect waves-light delete">
    <i class="material-icons">delete</i>
  </a>
</td>

このHTMLが「ゴミ箱のアイコン」を表示しています。

このHTMLにclickイベントを設定しましょう。

clickイベントを設定しよう

ゴミ箱のアイコン」にclickイベントを設定しましょう。

イベントを設定するにはイベントリスナーを使うのでしたね。

サンプルコードの「スタート」の「index.js」を見てみましょう。

clickイベントを設定しよう」と記述がされています。

その真下に、次のように書いてください。

// clickイベントを設定しよう
const deleteButton = clone.querySelector(".delete")
  deleteButton.addEventListener("click", () => {
  console.log('クリックされました!')
})

ゴミ箱のアイコン」は、template要素の中にあるのでコピーした要素から検索して取得しています。

const deleteButton = clone.querySelector(".delete")

取得した要素にaddEventListenerclickイベントのイベントハンドラを設定しています。

deleteButton.addEventListener("click", () => {
  console.log('クリックされました!')
})

動きを見てみましょう。コンソールに「クリックされました!」が出るはずです。

削除されるタスクを取得する

clickイベントが設定できたら、次は削除対象のタスクを取得しましょう。

削除対象のタスクはどのように取得すればいいでしょうか。

サンプルコードの「スタート」の「index.js」を見てみましょう。

タスクの配列データを作ったときにidを指定していましたね。

const tasks = [
  { id: 1, name: "部屋の後片付け" },
  { id: 2, name: "お買い物" },
]

このidは各リストのid属性に設定しています。

// trタグにid属性を追加する
tr.setAttribute("id", t.id)

デベロッパーメニューの「Elements」で見ると各リストにidが付与されているのが分かります。

このidを使って取得してみましょう。

idを使って取得する

サンプルコードの「スタート」の「index.js」を見てみましょう。

先ほどのclickのイベントハンドラの中に次のように書いてください。

// clickイベントを設定しよう
const deleteButton = clone.querySelector(".delete")
deleteButton.addEventListener("click", () => {
  const target = document.getElementById(t.id)

  console.log(target)
})

削除対象のタスクをidから検索しています。

const target = document.getElementById(task.id)

動きを見てみましょう。コンソールに削除対象のタスクのtr要素が出るはずです。

タスクをリストから削除する

次に、タスクをリストから削除してみましょう。

サンプルコードの「スタート」の「index.js」を見てみましょう。

先ほどのclickのイベントハンドラの中に次のように書いてください。

// clickイベントを設定しよう
const deleteButton = clone.querySelector(".delete")
deleteButton.addEventListener("click", () => {
  const target = document.getElementById(t.id)

  tbody.removeChild(target)

  document.removeEventListener("click", deleteButton)
})

ここでリストからタスクを削除しています。

tbody.removeChild(target)

ここでは、設定されていたイベントリスナーを削除しています。

document.removeEventListener("click", deleteButton)
メモ
イベントリスナーは明示的に削除しないと メモリリーク というパフォーマンスの低下に繋がる恐れがあります。

メモリリークについて別の記事で詳しく解説しますね。

では、動きを見てみましょう。リストからタスクが削除されるはずです。

追加されたタスクに削除処理を実装する

タスクの削除処理を実装しました。

しかし、現状だと新しく追加されたタスクに対しては削除機能が実装されていません。

サンプルコードの「スタート」の「index.js」を見てみましょう。

// タスクを追加しよう

// イベントハンドラを設定しよう
const form = document.getElementById('form')
form.addEventListener("submit", (event) => {
  // デフォルトの処理をキャンセルする
  event.preventDefault()

  // 入力されたデータを取得しよう
  constinput = document.getElementById('input')
  constvalue = input.value

  if (!value) return

  // 新しいタスクデータを作る
  consttask = { id:tasks.length + 1, name:value }

  // 入力した内容をToDoリストに追加する
  constclone = template.content.cloneNode(true)
  consttr = clone.querySelector("tr")
  constname = clone.querySelector(".name")

  tr.setAttribute("id", task.id)
  name.textContent = task.name

  tbody.appendChild(clone)
})

このsubmitイベントハンドラの中にも削除の実装をしましょう。

次のように、コードを追加してください。

// タスクを追加しよう

// イベントハンドラを設定しよう
const form = document.getElementById('form')
form.addEventListener("submit", (event) => {
  // デフォルトの処理をキャンセルする
  event.preventDefault()

  // 入力されたデータを取得しよう
  constinput = document.getElementById('input')
  constvalue = input.value

  if (!value) return

  // 新しいタスクデータを作る
  consttask = { id:tasks.length + 1, name:value }

  // 入力した内容をToDoリストに追加する
  constclone = template.content.cloneNode(true)
  consttr = clone.querySelector("tr")
  constname = clone.querySelector(".name")

  tr.setAttribute("id", task.id)
  name.textContent = task.name

  // タスクを削除しよう
  // clickイベントを設定しよう
  constdeleteButton = clone.querySelector(".delete")
  deleteButton.addEventListener("click", () => {
  consttarget = document.getElementById(task.id)

  tbody.removeChild(target)
  document.removeEventListener("click", deleteButton)
})

tbody.appendChild(clone)
})

動きを見てみましょう。リストから新しいタスクが削除されるはずです。

全てのタスクを削除しよう

最後に、全てのタスクを削除する機能を実装しましょう。

サンプルコードの「スタート」の「index.js」を見てみましょう。

全てのタスクを削除しよう」と記述がされています。

その真下に、次のように書いてください。

// 全てのタスクを削除しよう
const deleteAllButton = document.getElementById("deleteAll")

deleteAllButton.addEventListener("click", () => {
  const tbody = document.getElementById("tasks")
  tbody.innerHTML = ""
})

同じように、clickイベントをイベントリスナーで設定しています。

イベントハンドラの中では、リストの中のHTMLを空にしています。

const tbody = document.getElementById("tasks")
tbody.innerHTML = ""

空にすることで全てのタスクを削除しています。

動きを見てみましょう。リストから全てのタスクが削除されるはずです。

まとめ

本章では、ToDoリストの削除機能を実装しました。

もし、うまく動かなかったら「完成形」フォルダを確認してください。

完成形のコードがあるので見比べてみましょう。

完成したコードを見ると同じようなコードがあることに気づいたかと思います。

これらは共通化させて関数にすることができます。

共通処理を関数化させることで、コードのメンテナンス性を向上させることができます。

次章では、この共通処理の関数化のやり方を見てみましょう。