質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.80%

TodoListで2つ以上文字列を入力した際、全てのリスト欄が最後に入力した文字列に変化してしまう。

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 231

aki_

score 17

現象

JavaScriptでtodoリストを作っていますが、タスクを2つ以上作成した際、全てのタスクが最後に入力した文字列に変化してしまいます。

試したこと

一つだけ作成しようとすると最後に入力した文字列しか表示されなくなってしまい、他のタスクの文字は消えてしまうため、
for文で回してみたのですが、全てのタスクが最後に入力した文字列に変更されてしまいます。

現象が発生しているTodoリスト

http://nakatakira.html.xdomain.jp/test/test5/

手順

1.ADDING TASK欄に、タスクを書き込みます。
2.Enterキーを押下すると、チェックマークとゴミ箱が含まれたタスクが表示されます。
3.もう一度ADDING TASK欄にて、タスクを書き込みます。
4.全てのタスクが最後に入力したタスクの文字列に変化することを確認します。

'use strict'
{
    const addTask = document.getElementById('add');
    const list = document.getElementById('todos');
    const allDelBtn = document.getElementById('allDelBtn');
    const inputText= document.getElementById('inputText');

    addTask.addEventListener('submit', e => {
        // デフォルトのイベントを無効
        e.preventDefault();
        function createTodoList () {
            // HTMLテンプレートを生成
            todos.insertAdjacentHTML('beforeend',
            `<ul class="listGroup__item todos__item">
            <li class="todo__checkbox"><input type="checkbox" name="taskcheck" ></li>
            <li class="todo__task"></li>
            <li class="delete"></li>
            </ul>`)
            //todo__taskクラスを取得
            const todoTask = document.querySelectorAll('.todo__task');
            for(let i = 0; i < todoTask.length; i++){
            //タスク欄に入力した文字をテキストコンテンツとして出力(タグ無効)
                todoTask[i].textContent = inputText.value;
            };

            //チェックをつけると取り消し線が入る
            //document.querySelectorAllメソッドで一つでもリストとして取得することが可能
            //for文で回すことで、全ての中からcheckedになったもののみ取り消し線をつけることができる。
            //外すことも可能
            const taskCheck = document.querySelectorAll("input[type='checkbox']");
            for(let i = 0; i < taskCheck.length; i++){
                taskCheck[i].addEventListener('click', () => {
                        if(taskCheck[i].checked){
                                taskCheck[i].parentNode.nextElementSibling.style.textDecoration = 'line-through';
                            } else {
                                taskCheck[i].parentNode.nextElementSibling.style.textDecoration = 'none';
                            }
                    });    
                }
                //なお、allDelBtnを押すことでチェックがついたもののみ全て消すことも可能
                allDelBtn.addEventListener('click', e =>{
                for(let i = 0; i < taskCheck.length; i++){
                            if(taskCheck[i].checked=== true){
                                taskCheck[i].parentElement.parentElement.remove();
                            }
                    }
                })
        }    

        // タスクに入力した値を空白を除外して格納
        const task = addTask.add.value.trim();
        if(task.length) {
            // Todo List の HTML を生成
            createTodoList(task);
            // タスクに入力した文字をクリア
            addTask.reset();
        }
    });

    //一つずつゴミ箱で削除することも可能。deleteがクラスについている場合(つまりゴミ箱)。
    //親要素もろとも消し去る。JavaScriptで生成されたアイテムのためこのような記述になる
    list.addEventListener('click', e => {
        if (e.target.classList.contains('delete')){
            e.target.parentElement.remove();
        }
    });

}    


※コンソールにもエラーが表示されないことを確認しております。

追記
自己解決したわけではないのでこちらに書かせていただきます。
ありがとうございました!

'use strict'
{
    const addTask = document.getElementById('add');
    const list = document.getElementById('todos');
    const allDelBtn = document.getElementById('allDelBtn');
    const inputText= document.getElementById('inputText');
    //エスケープ処理
    function escText (str){
        return String(str).replace(/&/g,"&amp;")
            .replace(/"/g,"&quot;")
            .replace(/</g,"&lt;")
            .replace(/>/g,"&gt;")
            .replace(/>/g,"&gt;")
            .replace(/\//g, "&#047;")
    }

    addTask.addEventListener('submit', e => {
        // デフォルトのイベントを無効
        e.preventDefault();

        function createTodoList () {
            // HTMLテンプレートを生成
            //inputText.valueに対して、エスケープ処理関数を用いる
            todos.insertAdjacentHTML('beforeend',
            `<ul class="listGroup__item todos__item">
            <li class="todo__checkbox"><input type="checkbox" name="taskcheck" ></li>
            <li class="todo__task">${escText(inputText.value)}</li>
            <li class="delete"></li>
            </ul>`)
        ; 

            //チェックをつけると取り消し線が入る
            //document.querySelectorAllメソッドで一つでもリストとして取得することが可能
            //for文で回すことで、全ての中からcheckedになったもののみ取り消し線をつけることができる。
            //外すことも可能
            const taskCheck = document.querySelectorAll("input[type='checkbox']");
            for(let i = 0; i < taskCheck.length; i++){
                taskCheck[i].addEventListener('click', () => {
                        if(taskCheck[i].checked){
                                taskCheck[i].parentNode.nextElementSibling.style.textDecoration = 'line-through';
                            } else {
                                taskCheck[i].parentNode.nextElementSibling.style.textDecoration = 'none';
                            }
                    });    
                }
                //なお、allDelBtnを押すことでチェックがついたもののみ全て消すことも可能
                allDelBtn.addEventListener('click', e =>{
                for(let i = 0; i < taskCheck.length; i++){
                            if(taskCheck[i].checked=== true){
                                taskCheck[i].parentElement.parentElement.remove();
                            }
                    }
                })
        }    

        // タスクに入力した値を空白を除外して格納
        const task = addTask.add.value.trim();
        if(task.length) {
            // Todo List の HTML を生成
            createTodoList(task);
            // タスクに入力した文字をクリア
            addTask.reset();
        }
    });

    //一つずつゴミ箱で削除することも可能。deleteがクラスについている場合(つまりゴミ箱)。
    //親要素もろとも消し去る。JavaScriptで生成されたアイテムのためこのような記述になる
    list.addEventListener('click', e => {
        if (e.target.classList.contains('delete')){
            e.target.parentElement.remove();
        }
    });


}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

全てのリスト欄が最後に入力した文字列に変化してしまう

下記の部分で.todo__taskのコンテンツを全てinputText.valueに書き換えています。

//todo__taskクラスを取得
const todoTask = document.querySelectorAll('.todo__task');
for(let i = 0; i < todoTask.length; i++){
    //タスク欄に入力した文字をテキストコンテンツとして出力(タグ無効)
    todoTask[i].textContent = inputText.value;
};

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/04/25 19:23

    であれば、inputText.valueをエスケープ処理すると良いです。
    https://hacknote.jp/archives/55765/

    キャンセル

  • 2020/04/25 20:09

    ありがとうございます。
    エスケープ処理関数(ここではescText)を一番外側に置き、
    insertAdjacentHTMLテンプレートリテラル内の$部分、
    ${(escText=inputText.value)}にしたら
    上手くいきました。

    キャンセル

  • 2020/04/25 20:58

    やり方は色々あって、とくにTodoリストはチュートリアルとしていろんなものが出回っているので、
    参考してみたら良いと思います。
    とりあえず問題が解決できて良かったです^^

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.80%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る