tiiti
@tiiti

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

TODOリストの削除ボタンについてアドバイスいただきたいです。

filterを使用し任意のタスクを削除(ある意味非表示)にしたいです。

該当するソースコード

const createdeleteButton = (task) => {
  const deletebutton = document.createElement("button");
  deletebutton.innerText = "削除";
  deletebutton.style.backgroundColor = "lightgray";
  deletebutton.addEventListener("click", () => {
    if (radiowork.checked) {
      // const result = tasks.filter((task) => task.status === "作業中");
      showTaskList(result);
      const resultdelete = tasks.filter((task) => !task.id(/task.id/));
      showTaskList(resultdelete);
      console.log("作業中削除後", resulttasks);
      console.log("作業中の削除タスク", resultdelete);
//まずは作業中のタスクの削除ボタンの実装に取り掛かってます。
    } else if (radiocomplete.checked) {
      const result2 = tasks.filter((task) => task.status === "完了");
      showTaskList(result2);
      console.log("完了削除後", resulttasks);
    } else if (radioall.checked) {
      showTaskList(tasks);
    }
  });
  return deletebutton;
};

自分で試したこと

色々な方法を試したのですがうまくいかず、下記の方向性で削除ボタンを実装しようと考えています。
ラジオボタン「作業中」をクリック
→作業中のタスクのみ表示
→特定のタスクの削除ボタンを押す
→フィルターをかけ、削除ボタンが押されたタスク以外の「作業中」のタスクを表示させる
!を使用すれば配列の特定の要素をスキップできると拝見したので使用できないかと考えているのですが、
削除ボタンを押されたタスク以外を表示させたいため、ターゲットが動的に変化するので
実装方法に躓いてしまっています。

拙い文章ですみません。
また、上記コードは色々試してみた名残なのでお見苦しく申し訳ないです。

const input = document.getElementById("addbutton");
const tbody = document.getElementById("tbody");
const radiowork = document.getElementById("radio-work");
const radiocomplete = document.getElementById("radio-complete");
const radioall = document.getElementById("radio-all");

const tasks = [];
const createStatusButton = (task) => {
  const button = document.createElement("button");
  button.innerText = task.status;
  button.style.backgroundColor = "lightgray";
  button.addEventListener("click", () => {
    const buttonStatus = button.innerText;
    // console.log("変更前", task);

    if (buttonStatus === "作業中" && radiowork.checked) {
      button.textContent = "完了";
      task.status = "完了";
      const result = tasks.filter((task) => task.status === "作業中");
      showTaskList(result);
    } else if (buttonStatus === "完了" && radiocomplete.checked) {
      button.textContent = "作業中";
      task.status = "作業中";
      const result2 = tasks.filter((task) => task.status === "完了");
      showTaskList(result2);
    } else if (radioall.checked) {
      if (task.status === "作業中") {
        button.textContent = "完了";
        task.status = "完了";
      } else {
        button.textContent = "作業中";
        task.status = "作業中";
      }
      showTaskList(tasks);
    }
    // console.log("変更後", task);
  });

  return button;
};

const createdeleteButton = (task) => {
  const deletebutton = document.createElement("button");
  deletebutton.innerText = "削除";
  deletebutton.style.backgroundColor = "lightgray";
  deletebutton.addEventListener("click", () => {
    if (radiowork.checked) {
      // const result = tasks.filter((task) => task.status === "作業中");
      showTaskList(result);
      const resultdelete = tasks.filter((task) => !task.id(/task.id/));
      showTaskList(resultdelete);
      console.log("作業中削除後", resulttasks);
      console.log("作業中の削除タスク", resultdelete);
    } else if (radiocomplete.checked) {
      const result2 = tasks.filter((task) => task.status === "完了");
      showTaskList(result2);
      console.log("完了削除後", resulttasks);
    } else if (radioall.checked) {
      showTaskList(tasks);
    }
  });
  return deletebutton;
};

const showTaskList = (filteredTasks) => {
  console.log("filteredTasks", tasks);
  tbody.innerHTML = "";
  filteredTasks.forEach((task) => {
    const tr = document.createElement("tr");
    const td1 = document.createElement("td");
    td1.innerHTML = `${task.id}`;
    const td2 = document.createElement("td");
    td2.innerHTML = `${task.comment}`;
    const td3 = document.createElement("td");
    const td4 = document.createElement("td");
    tbody.appendChild(tr);
    tr.appendChild(td1);
    tr.appendChild(td2);
    tr.appendChild(td3);
    tr.appendChild(td4);
    td3.appendChild(createStatusButton(task));
    td4.appendChild(createdeleteButton(task));
  });
};

const tasksStatus = document.getElementById("statusradio");
const text = document.getElementById("tasks");

input.addEventListener("click", () => {
  const text = document.getElementById("tasks");
  if (text.value === "") {
    alert("タスクを入力してください");
  } else {
    tasks.push({
      id: tasks.length + 1,
      comment: text.value,
      status: "作業中",
    });
    if (radiowork.checked) {
      const result = tasks.filter((task) => task.status === "作業中");
      showTaskList(result);
    } else if (radiocomplete.checked) {
      const result2 = tasks.filter((task) => task.status === "完了");
      showTaskList(result2);
    } else if (radioall.checked) {
      showTaskList(tasks);
    }
    text.value = "";
  }
});

radiowork.addEventListener("change", () => {
  console.log(tasks); // ラジオボタン(作業中)がクリックされた時のタスクを表示
  const result = tasks.filter((task) => task.status === "作業中");
  console.log("result", result); // フィルターをかけた後のタスクのみをコンソールに出力
  showTaskList(result);
});

// ラジオボタン(完了)がクリックされた時
radiocomplete.addEventListener("change", () => {
  const result2 = tasks.filter((task) => task.status === "完了");
  console.log("result", result2);
  showTaskList(result2);
});

// ラジオボタン(完了)がクリックされた時
radioall.addEventListener("change", () => {
  showTaskList(tasks);
});
0

2Answer

HTMLがあるとこちらも動作確認できます。
公開するのが難しい場合、スクリーンショットや画面イメージ(四角や丸だけのもの)を添付してもらえると回答側にとってイメージしやすくなります。

今はざっくり、こういうテーブルがある認識です。

id comment 状態 削除
1 タスク [作業中] [削除]
2 タスク [完了] [削除]

また、ラジオボタンの「作業中」「完了」「全部」のどれかが必ず付いていると考えています。
上記の前提で話しますが、間違っていたら訂正お願いします。

まず、!を使用してフィルタリングしたいとのことですが、残念ながら下記の書き方は間違っています。
Uncaught TypeError: task.id is not a functionのエラーが出てくるはずです。

const resultdelete = tasks.filter((task) => !task.id(/task.id/));

!task.idを使用した書き方はこちらです。

const resultdelete = tasks.filter((task) => !task.id);

理由はエラー文通り、task.idはnumberでありfunctionではないため、id()のような書き方ができません。

日本語にすると、「tasksの中からidが存在しないタスクを抽出する」ことになります。
質問者様の意図とは別物です。

!を使用すれば配列の特定の要素をスキップできると拝見した

おそらくご参考にされたコードではそういう使い方かと思いますが、!(論理否定演算子)自身の意味はそれではありません。
一度調べてみた方がいいでしょう。

そもそも、削除ボタンが押された後に、tasksのタスクに対しての操作がありません。
何もしていなくて、再度フィルタリングを掛けただけなので、画面に変化が出ません。

フィルタリングに!を使いたいのをこだわらなければ、他の方法をおすすめします。
例えばtask.status"作業中""完了"しか存在しませんが、そこに「削除された」と等しい状態を追加するとか。
(本当は日本語の文字列ではなく、numberやenumがいいです。。。)
その後は、作業中でフィルタリングすればいいです。
ラジオボタン「作業中」が選択された際の実装と同じでいいです。

  deletebutton.addEventListener("click", () => {
   // 削除ボタンが押されたら状態変更
+   task.status = "削除";  // 日本語じゃない方がいい
    if (radiowork.checked) {
      // このままで合っているのでアンコメント
-     // const result = tasks.filter((task) => task.status === "作業中");
+     const result = tasks.filter((task) => task.status === "作業中");
      showTaskList(result);
-     const resultdelete = tasks.filter((task) => !task.id(/task.id/));
-     showTaskList(resultdelete);
-     console.log("作業中削除後", resulttasks);
+     console.log("作業中削除後", result);  // 定義されていないresulttasksではなくresultを出力
-     console.log("作業中の削除タスク", resultdelete);
    } else if (radiocomplete.checked) {
    } else if (radioall.checked) {
    }
  });

変更を加えたい時は、taskに変更を加えて、
あとは通常通りにフィルタリングすれば問題ないかと思います。
これはcreateStatusButtonの方にも当てはまります。

最後に、他の回答者様の意見に関連するものになりますが、
宣言する際に、constが使えるなら使いましょう。let、ましてやvarに変更するメリットはありません。
今のままで大丈夫です。

1Like

Comments

  1. @tiiti

    Questioner

    ご返信が遅くなり申し訳ございません!
    ご丁寧な回答を誠にありがとうございます!!
    自分の進め方より、スムーズに実装できました。。。

var let でオブジェクト変数を定義してはどうでしょうか?
constの多様が異様に感じます。
因みにletはスコープがブロック範囲で書き換え可能な変数を宣言します。

let deletebutton = document.createElement("button");
  deletebutton.innerText = "削除";
叉は
document.createElement("button").innerText = "削除";
0Like

Comments

  1. @tiiti

    Questioner

    ご回答誠にありがとうございます!!
    参考にさせていただきました!!

Your answer might help someone💌