質問: '完了'}); return showTodos(doneTodos); } }; radioButton.forEach((e, number) => { radioButton[number].addEventListener('click', () => { filterTodos(); }); }); ``` ### 発生している問題 私の実現したい機能は、 `フィルタリングしてもIDは変わらない`と `タスク削除後IDが新しく振り直される`の2つを兼ね備えたものです。 どちらか1つの機能は実現できるのですが、両方の機能を実現できません。 IDを表示するに当たり、以下の2つの方法で試みました。 `1. forEachの中でtd要素を作り、todos配列のindex番号をIDの値として使用。` →タスクを削除した場合、IDが振り直される。◯ →フィルタリングした場合、IDは元のIDのまま。✕ `2. nextIdを定義し、id: nextId++ とする。` →タスクを削除した場合、IDが振り直される。☓ →フィルタリングした場合、IDは元のIDのまま。◯ 現状nextIdのやり方でIDを定義しています。 nextId++としているのでIDが只々増えていってしまうのは承知の上なのですが、 どうすればidを振り直すことができるのか解決方法が見つけられません。 実装できない原因として、以下のものが浮かんでいます。 ・定義したidの管理の仕方を把握していない。 ・idの取得方法が間違っている。 ・idを毎回取得する仕組みを理解していない。 ### 試したこと 以下の2つの箇所で問題があると思い、改善を試みました。 `オブジェクトに入れるID` もしくは、 `td要素のtextContent` td要素のtext.Contentをtodo.idからnextId++にしてみたり、 indexやnumberを入れ替えたりしてみましたが上手くいかず、 根本的に実装方法が思いつきません。 削除ボタンを押したら、idを0から振り直す、 みたいな関数も作れるような気はするんですが、 どう作ればいいか検討が付きません。 IDをindexにした場合、逆にnextIdとした場合、 どちらも意図した挙動にならないのは理解できます。 しかし、それを解決する方法が見つけられない現状です。 どのように考えていけば良いのか、ヒントや実装方法を教えていただけたら幸いです。 以上です。 よろしくお願いいたします! ### 補足情報(FW/ツールのバージョンなど) エディタ:Visual Stadio Code
回答: うーん認識違いな気がする。 表示されている左端の『質問者さんがidと言っているもの』は 『idではなくて表示中のリストの順番』だと思います。私ならそうしますが。 というかソースだといろいろ動かないゾ...試しにこうしてみてください。 ``` // 「todos」の中身を一覧表示するための関数を用意する // const showTodos = (todos) => { tableBody.textContent = ''; // 値を1つずつ取り出し、繰り返し処理を実行 + // 引数増やしてインデックス取得 - todos.forEach((todo) => { + todos.forEach((todo,i) => { // tbody要素に追加するためのtr要素を作成し、子要素としてtrを追加 // const tableRecord = document.createElement('tr'); tableBody.appendChild(tableRecord); // tr要素に追加するためのtd要素をそれぞれ作成する // const tableId = document.createElement('th'); const tableComment = document.createElement('td'); const tableStatus = document.createElement('td'); const tableAction = document.createElement('td'); // 要素の中身のテキストを表示するため、オブジェクトの要素から取得する // - tableId.textContent = todo.id; + // インデックスを表示 + tableId.textContent = i; tableComment.textContent = todo.comment; // td要素をtr要素の子要素として追加する // tableRecord.appendChild(tableId); tableRecord.appendChild(tableComment); tableRecord.appendChild(tableStatus); tableRecord.appendChild(tableAction); tableStatus.appendChild(createStatusButton(todo)); // deleteのtodo.idはそのまま渡す tableAction.appendChild(createDeleteButton(tableRecord, todo.id)); }); }; //「状態機能」を管理するボタンを生成する関数 const createStatusButton = (todo) => { const statusButton = document.createElement('button'); statusButton.textContent = todo.status; statusButton.addEventListener('click', () => { if (todo.status === '作業中') { todo.status = '完了'; filterTodos() } else { todo.status = '作業中'; filterTodos(); } }); return statusButton; }; //「削除機能」を管理するボタンを生成する関数 const createDeleteButton = (tableRecord, id) => { let index = tableRecord.rowIndex - 1; const deleteButton = document.createElement('button'); deleteButton.textContent = '削除'; deleteButton.addEventListener('click', () => { const targetIndex = todos.findIndex(todo => { return todo.id === id; }); todos.splice(targetIndex, 1); filterTodos(); }); return deleteButton; }; + // これ未定義だよ!!!!!!!!!!!!!!!!!!!!!! + const radioButtonAll = document.getElementById('radio-all-select'); + const radioButtonWorking = document.getElementById('radio-woking-select'); + const radioButtonDone = document.getElementById('radio-done-select'); // 表示・非表示の機能を管理する関数 const filterTodos = () => { if (radioButtonAll.checked) { return showTodos(todos); } else if (radioButtonWorking.checked) { const doingTodos = todos.filter(todo => { return todo.status === '作業中' }); return showTodos(doingTodos); } else if (radioButtonDone.checked) { const doneTodos = todos.filter(todo => { return todo.status === '完了' }); return showTodos(doneTodos); } }; ``` ### 追記 削除後に振りなおすしかないでしょうね。 ``` // 「追加」ボタンがクリックされたときの処理を実装する // addButton.addEventListener('click', () => { // ここでidをとるとキャンセルしたときにおかしい inputBox.focus(); // 空文字が入力されたときの処理 if (inputBox.value === '') { alert('タスクを入力してください!'); return; } //todoがtrueの場合の処理 // この書き方はすべてtrueなので意味なし //if (todo) { // push直前でid取得 const todo = { id: todos.length, comment: inputBox.value, status: '作業中' } todos.push(todo); inputBox.value = ''; showTodos(todos); filterTodos(); //} }); //「削除機能」を管理するボタンを生成する関数 const createDeleteButton = (tableRecord, id) => { let index = tableRecord.rowIndex - 1; const deleteButton = document.createElement('button'); deleteButton.textContent = '削除'; deleteButton.addEventListener('click', () => { const targetIndex = todos.findIndex(todo => { return todo.id === id; }); todos.splice(targetIndex, 1); // 削除後に削除id以上を振りなおす for (var i = targetIndex; i < todos.length; i++) { todos[i].id = i } filterTodos(); }); return deleteButton; }; ```