0

I am making this Todo list, but I get the following error.

https://gyazo.com/0b47106078622a1e44e912f56b5e9603

<error> main.js:79 Uncaught TypeError: Cannot read property 'addEventListener' of null

I thought it was due to a misspelling or an id that could not be defined.... I would like to know the solution here.

{
  document.addEventListener('DOMContentLoaded', () => {
    const addTaskTrigger = document.getElementsByClassName('addTask-trigger')[0];
    const addTaskTarget = document.getElementsByClassName('addTask-target')[0];
    const addTaskValue = document.getElementsByClassName('addTask-value')[0];
    const radioWork = document.getElementById('#radio-work'); //Radio button id working
    const radioDone = document.getElementById('#radio-done'); //Radio button completion id
    let nextId = 0;
    const todos = [];

    //Taskとidを作成
    const addTask = (task, id, tableItem) => {
      const idSpanTd = document.createElement('td');
      const taskSpanTd = document.createElement('td');
      //タスク追加時にtodosにtodoを追加 
      const todo = {
        task: 'taskSpanTd',
        status: '作業中'
      };
      todos.push(todo);
      //要素内のHTML文章を変更する
      idSpanTd.innerText = id;
      taskSpanTd.innerText = task;
      //生成したテーブル要素をブラウザに表示する
      tableItem.append(idSpanTd);
      tableItem.append(taskSpanTd);
      addTaskTarget.append(tableItem);
    };

    //Button要素を生成する
    const addButton = (tableItem, removeButton, createButton) => {
      const createButtonTd = document.createElement('td');
      const removeButtonTd = document.createElement('td');
      //要素内のHTML文章を変更する
      createButton.innerText = '作業中';
      removeButton.innerText = '削除';
      //生成したテーブル要素をブラウザに表示する
      tableItem.append(createButtonTd);
      tableItem.append(removeButtonTd);
      addTaskTarget.append(tableItem);
      //生成したbutton要素を生成する
      createButtonTd.append(createButton);
      removeButtonTd.append(removeButton);
    };

    //追加ボタンをクリックした際にtd要素を追加する処理を行う
    addTaskTrigger.addEventListener('click', () => {
      const task = addTaskValue.value;
      const tableItem = document.createElement('tr');
      const removeButton = document.createElement('button');
      const createButton = document.createElement('button');
      addTask(task, nextId++, tableItem);
      addButton(tableItem, removeButton, createButton);
      addTaskValue.value = '';
      // //削除ボタンを押した時にタスクを削除する
      const deleteElement = (a) => {
        const tableTag = a.target.closest('tr');
        if (tableTag) tableTag.remove();
        updateId();
      }
      removeButton.addEventListener('click', deleteElement, false);

      //When you press the button, it changes from working to completion
      createButton.addEventListener('click', (a) => {
        if (createButton.textContent === "作業中") {
          createButton.textContent = "完了";
          const doneParent = a.target.parentNode;
          doneParent.className = 'workDone'; /*完了class*/
        } else {
          createButton.textContent = "作業中";
          const workParent = a.target.parentNode;
          workParent.className = 'work'; /*作業中class*/
        }
      });
    })

    //Processing when pressing the radio button in progress
    radioWork.addEventListener('click', function() {
      const workTasks = document.getElementsByClassName('work');
      workTsks = Array.from(workTasks);
      if (radioWork.checked === true) {
        workTasks.forEach(function(workTasks) {
          workTasks.style.display = "none";
        })
      } else {
        workTasks.forEach(function(workTasks) {
          workTasks.style.display = "";
        })
      }
    })

    // Processing when radio button complete is pressed
    radioDone.addEventListener('click', function() {
      const doneTasks = document.getElementsByClassName('workDone');
      doneTasks = Array.from(doneTasks);

      if (radioDone.checked === true) {
        doneTasks.forEach(function(doneTasks) {
          doneTasks.style.display = "none";
        })
      } else {
        doneTasks.forEach(function(doneTasks) {
          doneTasks.style.display = "none";
        })
      }
    })

    // 連番 再振り直し
    const updateId = () => {
      const tbody = document.getElementsByTagName("tbody")[0];
      const taskList = tbody.getElementsByTagName('tr');
      nextId = 0;
      Array.from(taskList, tr => {
        tr.getElementsByTagName('td')[0].textContent = nextId;
        nextId++
      });
    }
  });
}
<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="css/style.css">
  <title>Todoリスト</title>
</head>

<body>
  <h1>Todoリスト</h1>
  <p>
    <input type="radio" name="task" value="1" checked="checked">全て
    <input type="radio" name="task" value="2" id="radio-work">作業中
    <input type="radio" name="task" value="3" id="radio-done">完了
  </p>
  <p></p>
  <table>
    <thead>
      <th>ID</th>
      <th>コメント</th>
      <th>状態</th>
      <th></th>
    </thead>
    <tbody class="addTask-target" id="tbody"></tbody>
  </table>
  <h2>新規タスクの追加</h2>
  <input class="addTask-value" type="text" />
  <button class="addTask-trigger" type="button">追加</button>
  <script src="js/main.js"></script>
</body>

</html>
Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
kanata
  • 83
  • 7
  • usually this happen when js execute before the DOM is ready and at that point the element is not available in DOM so it is throwing null, are the error constantly happen ? – Rio A.P Jul 06 '20 at 03:33
  • Thank you for confirmation. Yes, its will always be.Is the solution such as changing the order of description? – kanata Jul 06 '20 at 03:44
  • Does this answer your question? [Why does \`document.getElementById("#sideNav")\` not find my element?](https://stackoverflow.com/questions/38479889/why-does-document-getelementbyidsidenav-not-find-my-element). Please minimize your issue; learn to use the [debugging capabilities](https://developer.mozilla.org/en-US/docs/Mozilla/Debugging/Debugging_JavaScript) of your browser; read the [docs](https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById). You don’t need all 150 lines of code to figure out that `Document.prototype.getElementById` expects an ID, not a CSS selector. – Sebastian Simon Jul 06 '20 at 04:36

2 Answers2

2

You should change get radio element by name as

 const task = document.getElementsByName("task");
 const radioWork = task[1]; //Radio button id working
 const radioDone = task[2]; //Radio button completion id

Or you can change order of input as (move the id to front)

<input type="radio" id="radio-work" name="task" value="2">作業中
<input type="radio" id="radio-done" name="task" value="3">完了

and change to (remove # character)

 const radioWork = document.getElementById('radio-work'); //Radio button id working
 const radioDone = document.getElementById('radio-done');

{
  document.addEventListener('DOMContentLoaded', () => {
    const addTaskTrigger = document.getElementsByClassName('addTask-trigger')[0];
    const addTaskTarget = document.getElementsByClassName('addTask-target')[0];
    const addTaskValue = document.getElementsByClassName('addTask-value')[0];
     const task = document.getElementsByName("task");
        const radioWork = task[1]; //Radio button id working
        const radioDone = task[2]; //Radio button completion id
    let nextId = 0;
    const todos = [];

    //Taskとidを作成
    const addTask = (task, id, tableItem) => {
      const idSpanTd = document.createElement('td');
      const taskSpanTd = document.createElement('td');
      //タスク追加時にtodosにtodoを追加 
      const todo = {
        task: 'taskSpanTd',
        status: '作業中'
      };
      todos.push(todo);
      //要素内のHTML文章を変更する
      idSpanTd.innerText = id;
      taskSpanTd.innerText = task;
      //生成したテーブル要素をブラウザに表示する
      tableItem.append(idSpanTd);
      tableItem.append(taskSpanTd);
      addTaskTarget.append(tableItem);
    };

    //Button要素を生成する
    const addButton = (tableItem, removeButton, createButton) => {
      const createButtonTd = document.createElement('td');
      const removeButtonTd = document.createElement('td');
      //要素内のHTML文章を変更する
      createButton.innerText = '作業中';
      removeButton.innerText = '削除';
      //生成したテーブル要素をブラウザに表示する
      tableItem.append(createButtonTd);
      tableItem.append(removeButtonTd);
      addTaskTarget.append(tableItem);
      //生成したbutton要素を生成する
      createButtonTd.append(createButton);
      removeButtonTd.append(removeButton);
    };

    //追加ボタンをクリックした際にtd要素を追加する処理を行う
    addTaskTrigger.addEventListener('click', () => {
      const task = addTaskValue.value;
      const tableItem = document.createElement('tr');
      const removeButton = document.createElement('button');
      const createButton = document.createElement('button');
      addTask(task, nextId++, tableItem);
      addButton(tableItem, removeButton, createButton);
      addTaskValue.value = '';
      // //削除ボタンを押した時にタスクを削除する
      const deleteElement = (a) => {
        const tableTag = a.target.closest('tr');
        if (tableTag) tableTag.remove();
        updateId();
      }
      removeButton.addEventListener('click', deleteElement, false);

      //When you press the button, it changes from working to completion
      createButton.addEventListener('click', (a) => {
        if (createButton.textContent === "作業中") {
          createButton.textContent = "完了";
          const doneParent = a.target.parentNode;
          doneParent.className = 'workDone';/*完了class*/
        } else {
          createButton.textContent = "作業中";
          const workParent = a.target.parentNode;
          workParent.className = 'work';/*作業中class*/
        }
      });
    })

    //Processing when pressing the radio button in progress
    radioWork.addEventListener('click', function () {
      const workTasks = document.getElementsByClassName('work');
      workTsks = Array.from(workTasks);
      if (radioWork.checked === true) {
        workTasks.forEach(function (workTasks) {
          workTasks.style.display = "none";
        })
      } else {
        workTasks.forEach(function (workTasks) {
          workTasks.style.display = "";
        })
      }
    })

    // Processing when radio button complete is pressed
    radioDone.addEventListener('click', function () {
      const doneTasks = document.getElementsByClassName('workDone');
      doneTasks = Array.from(doneTasks);

      if (radioDone.checked === true) {
        doneTasks.forEach(function (doneTasks) {
          doneTasks.style.display = "none";
        })
      } else {
        doneTasks.forEach(function (doneTasks) {
          doneTasks.style.display = "none";
        })
      }
    })

    // 連番 再振り直し
    const updateId = () => {
      const tbody = document.getElementsByTagName("tbody")[0];
      const taskList = tbody.getElementsByTagName('tr');
      nextId = 0;
      Array.from(taskList, tr => {
        tr.getElementsByTagName('td')[0].textContent = nextId;
        nextId++
      });
    }
  });
}
<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="css/style.css">
  <title>Todoリスト</title>
</head>

<body>
  <h1>Todoリスト</h1>
  <p>
    <input type="radio" name="task" value="1" checked ="checked">全て
    //<input type="radio" name="task" value="2" id="radio-work">作業中
    //<input type="radio" name="task" value="3" id="radio-done">完了
 <input type="radio" id="radio-work" name="task" value="2">作業中
<input type="radio" id="radio-done" name="task" value="3">完了
  </p>
  <p></p>
  <table>
    <thead>
      <th>ID</th>
      <th>コメント</th>
      <th>状態</th>
      <th></th>
    </thead>
    <tbody class="addTask-target" id="tbody"></tbody>
  </table>
  <h2>新規タスクの追加</h2>
  <input class="addTask-value" type="text" />
  <button class="addTask-trigger" type="button">追加</button>
  <script src="js/main.js"></script>
</body>
</html>
Always Helping
  • 14,316
  • 4
  • 13
  • 29
Hien Nguyen
  • 24,551
  • 7
  • 52
  • 62
1

You can change order of input as (move the id to front)

<input type="radio" id="radio-work" name="task" value="2">作業中
<input type="radio" id="radio-done" name="task" value="3">完了

and change to (remove # character)

const radioWork = document.getElementById('radio-work'); //Radio button id working
 const radioDone = document.getElementById('radio-done');

 {
      document.addEventListener('DOMContentLoaded', () => {
        const addTaskTrigger = document.getElementsByClassName('addTask-trigger')[0];
        const addTaskTarget = document.getElementsByClassName('addTask-target')[0];
        const addTaskValue = document.getElementsByClassName('addTask-value')[0];
        const task = document.getElementsByName("task");
        const radioWork = document.getElementById("radio-work"); //Radio button id working
        const radioDone = document.getElementById("radio-done"); //Radio button completion id
        let nextId = 0;
        const todos = [];

        //Taskとidを作成
        const addTask = (task, id, tableItem) => {
          const idSpanTd = document.createElement('td');
          const taskSpanTd = document.createElement('td');
          //タスク追加時にtodosにtodoを追加 
          const todo = {
            task: 'taskSpanTd',
            status: '作業中'
          };
          todos.push(todo);
          //要素内のHTML文章を変更する
          idSpanTd.innerText = id;
          taskSpanTd.innerText = task;
          //生成したテーブル要素をブラウザに表示する
          tableItem.append(idSpanTd);
          tableItem.append(taskSpanTd);
          addTaskTarget.append(tableItem);
        };

        //Button要素を生成する
        const addButton = (tableItem, removeButton, createButton) => {
          const createButtonTd = document.createElement('td');
          const removeButtonTd = document.createElement('td');
          //要素内のHTML文章を変更する
          createButton.innerText = '作業中';
          removeButton.innerText = '削除';
          //生成したテーブル要素をブラウザに表示する
          tableItem.append(createButtonTd);
          tableItem.append(removeButtonTd);
          addTaskTarget.append(tableItem);
          //生成したbutton要素を生成する
          createButtonTd.append(createButton);
          removeButtonTd.append(removeButton);
        };

        //追加ボタンをクリックした際にtd要素を追加する処理を行う
        addTaskTrigger.addEventListener('click', () => {
          const task = addTaskValue.value;
          const tableItem = document.createElement('tr');
          const removeButton = document.createElement('button');
          const createButton = document.createElement('button');
          addTask(task, nextId++, tableItem);
          addButton(tableItem, removeButton, createButton);
          addTaskValue.value = '';
          // //削除ボタンを押した時にタスクを削除する
          const deleteElement = (a) => {
            const tableTag = a.target.closest('tr');
            if (tableTag) tableTag.remove();
            updateId();
          }
          removeButton.addEventListener('click', deleteElement, false);

          //When you press the button, it changes from working to completion
          createButton.addEventListener('click', (a) => {
            if (createButton.textContent === "作業中") {
              createButton.textContent = "完了";
              const doneParent = a.target.parentNode;
              doneParent.className = 'workDone';/*完了class*/
            } else {
              createButton.textContent = "作業中";
              const workParent = a.target.parentNode;
              workParent.className = 'work';/*作業中class*/
            }
          });
        })

        //Processing when pressing the radio button in progress
        radioWork.addEventListener('click', function () {
          const workTasks = document.getElementsByClassName('work');
          workTsks = Array.from(workTasks);
          if (radioWork.checked === true) {
            workTasks.forEach(function (workTasks) {
              workTasks.style.display = "none";
            })
          } else {
            workTasks.forEach(function (workTasks) {
              workTasks.style.display = "";
            })
          }
        })

        // Processing when radio button complete is pressed
        radioDone.addEventListener('click', function () {
          const doneTasks = document.getElementsByClassName('workDone');
          doneTasks = Array.from(doneTasks);

          if (radioDone.checked === true) {
            doneTasks.forEach(function (doneTasks) {
              doneTasks.style.display = "none";
            })
          } else {
            doneTasks.forEach(function (doneTasks) {
              doneTasks.style.display = "none";
            })
          }
        })

        // 連番 再振り直し
        const updateId = () => {
          const tbody = document.getElementsByTagName("tbody")[0];
          const taskList = tbody.getElementsByTagName('tr');
          nextId = 0;
          Array.from(taskList, tr => {
            tr.getElementsByTagName('td')[0].textContent = nextId;
            nextId++
          });
        }
      });
    }
<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="css/style.css">
  <title>Todoリスト</title>
</head>

<body>
  <h1>Todoリスト</h1>
  <p>
    <input type="radio" name="task" value="1" checked="checked">全て
    <input type="radio" id="radio-work" name="task" value="2">作業中
    <input type="radio" id="radio-done" name="task" value="3">完了
  </p>
  <p></p>
  <table>
    <thead>
      <th>ID</th>
      <th>コメント</th>
      <th>状態</th>
      <th></th>
    </thead>
    <tbody class="addTask-target" id="tbody"></tbody>
  </table>
  <h2>新規タスクの追加</h2>
  <input class="addTask-value" type="text" />
  <button class="addTask-trigger" type="button">追加</button>
  <script src="js/main.js"></script>
  <script>
   
  </script>
</body>

</html>
Hien Nguyen
  • 24,551
  • 7
  • 52
  • 62