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

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

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

734閲覧

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

aki_

総合スコア18

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2020/04/25 05:08

編集2020/04/25 11:10

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

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

##現象が発生しているTodoリスト
http://nakatakira.html.xdomain.jp/test/test5/

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

JavaScript

1'use strict' 2{ 3 const addTask = document.getElementById('add'); 4 const list = document.getElementById('todos'); 5 const allDelBtn = document.getElementById('allDelBtn'); 6 const inputText= document.getElementById('inputText'); 7 8 addTask.addEventListener('submit', e => { 9 // デフォルトのイベントを無効 10 e.preventDefault(); 11 function createTodoList () { 12 // HTMLテンプレートを生成 13 todos.insertAdjacentHTML('beforeend', 14 `<ul class="listGroup__item todos__item"> 15 <li class="todo__checkbox"><input type="checkbox" name="taskcheck" ></li> 16 <li class="todo__task"></li> 17 <li class="delete"></li> 18 </ul>`) 19 //todo__taskクラスを取得 20 const todoTask = document.querySelectorAll('.todo__task'); 21 for(let i = 0; i < todoTask.length; i++){ 22 //タスク欄に入力した文字をテキストコンテンツとして出力(タグ無効) 23 todoTask[i].textContent = inputText.value; 24 }; 25 26 //チェックをつけると取り消し線が入る 27 //document.querySelectorAllメソッドで一つでもリストとして取得することが可能 28 //for文で回すことで、全ての中からcheckedになったもののみ取り消し線をつけることができる。 29 //外すことも可能 30 const taskCheck = document.querySelectorAll("input[type='checkbox']"); 31 for(let i = 0; i < taskCheck.length; i++){ 32 taskCheck[i].addEventListener('click', () => { 33 if(taskCheck[i].checked){ 34 taskCheck[i].parentNode.nextElementSibling.style.textDecoration = 'line-through'; 35 } else { 36 taskCheck[i].parentNode.nextElementSibling.style.textDecoration = 'none'; 37 } 38 }); 39 } 40 //なお、allDelBtnを押すことでチェックがついたもののみ全て消すことも可能 41 allDelBtn.addEventListener('click', e =>{ 42 for(let i = 0; i < taskCheck.length; i++){ 43 if(taskCheck[i].checked=== true){ 44 taskCheck[i].parentElement.parentElement.remove(); 45 } 46 } 47 }) 48 } 49 50 // タスクに入力した値を空白を除外して格納 51 const task = addTask.add.value.trim(); 52 if(task.length) { 53 // Todo List の HTML を生成 54 createTodoList(task); 55 // タスクに入力した文字をクリア 56 addTask.reset(); 57 } 58 }); 59 60 //一つずつゴミ箱で削除することも可能。deleteがクラスについている場合(つまりゴミ箱)。 61 //親要素もろとも消し去る。JavaScriptで生成されたアイテムのためこのような記述になる 62 list.addEventListener('click', e => { 63 if (e.target.classList.contains('delete')){ 64 e.target.parentElement.remove(); 65 } 66 }); 67 68} 69

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

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

JavaScript

1'use strict' 2{ 3 const addTask = document.getElementById('add'); 4 const list = document.getElementById('todos'); 5 const allDelBtn = document.getElementById('allDelBtn'); 6 const inputText= document.getElementById('inputText'); 7    //エスケープ処理 8 function escText (str){ 9 return String(str).replace(/&/g,"&amp;") 10 .replace(/"/g,"&quot;") 11 .replace(/</g,"&lt;") 12 .replace(/>/g,"&gt;") 13 .replace(/>/g,"&gt;") 14 .replace(///g, "&#047;") 15 } 16 17 addTask.addEventListener('submit', e => { 18 // デフォルトのイベントを無効 19 e.preventDefault(); 20 21 function createTodoList () { 22 // HTMLテンプレートを生成 23 //inputText.valueに対して、エスケープ処理関数を用いる 24 todos.insertAdjacentHTML('beforeend', 25 `<ul class="listGroup__item todos__item"> 26 <li class="todo__checkbox"><input type="checkbox" name="taskcheck" ></li> 27 <li class="todo__task">${escText(inputText.value)}</li> 28 <li class="delete"></li> 29 </ul>`) 30 ; 31 32 //チェックをつけると取り消し線が入る 33 //document.querySelectorAllメソッドで一つでもリストとして取得することが可能 34 //for文で回すことで、全ての中からcheckedになったもののみ取り消し線をつけることができる。 35 //外すことも可能 36 const taskCheck = document.querySelectorAll("input[type='checkbox']"); 37 for(let i = 0; i < taskCheck.length; i++){ 38 taskCheck[i].addEventListener('click', () => { 39 if(taskCheck[i].checked){ 40 taskCheck[i].parentNode.nextElementSibling.style.textDecoration = 'line-through'; 41 } else { 42 taskCheck[i].parentNode.nextElementSibling.style.textDecoration = 'none'; 43 } 44 }); 45 } 46 //なお、allDelBtnを押すことでチェックがついたもののみ全て消すことも可能 47 allDelBtn.addEventListener('click', e =>{ 48 for(let i = 0; i < taskCheck.length; i++){ 49 if(taskCheck[i].checked=== true){ 50 taskCheck[i].parentElement.parentElement.remove(); 51 } 52 } 53 }) 54 } 55 56 // タスクに入力した値を空白を除外して格納 57 const task = addTask.add.value.trim(); 58 if(task.length) { 59 // Todo List の HTML を生成 60 createTodoList(task); 61 // タスクに入力した文字をクリア 62 addTask.reset(); 63 } 64 }); 65 66 //一つずつゴミ箱で削除することも可能。deleteがクラスについている場合(つまりゴミ箱)。 67 //親要素もろとも消し去る。JavaScriptで生成されたアイテムのためこのような記述になる 68 list.addEventListener('click', e => { 69 if (e.target.classList.contains('delete')){ 70 e.target.parentElement.remove(); 71 } 72 }); 73 74 75}

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

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

下記の部分で.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 05:37

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

aki_

2020/04/25 05:59

ありがとうございます!.todo__taskの内容をdocument.querySelectorAllですべて書き換えてしまっていることを確認いたしました。 しかしtodoTaskの部分をdocument.querySelectorに変更したら、何も表示されなくなったことを確認しております。 「const todoTask = document.querySelector('.todo__task');」をfor文の中に入れるのが一番いいと思われますが、for文を回すための「todoTask.length」をどの要素を取得するのに変更すればいいのかわからないでいます。insertAdjacentHTMLのほかの要素を入れてみたのですが(例えばulタグの回数など)うまく回らないことを確認しております。
退会済みユーザー

退会済みユーザー

2020/04/25 06:24

新規タスクを追加する際に、既存のタスクに何か処理を加える必要がなければ、 前述した記述は丸っと削除していいと思います。 その代わりに、insertAdjacentHTMLで新規タスクを追加す際、 一緒にinputText.valueを渡すのが良いと思いますが、いかがでしょう。 なにか理由があって別でコンテンツを入れているのであればダメでしょうけど、、、 `<ul class="listGroup__item todos__item"> <li class="todo__checkbox"><input type="checkbox" name="taskcheck" ></li> <li class="todo__task">${inputText.value}</li> <li class="delete"></li> </ul>`
aki_

2020/04/25 08:49

たしかにinputText.valueだと文字を出力することができます。 ただ、${inputText.value}のみだと、addTask欄にもし<p>や<input>などのタグを入れた場合、HTMLタグとして出力されてしまうことなのです。セキュリティ的に問題が発生する心配があります。 inputText.valueの部分はあくまでも文字列として出力したいのですが、何かいい方法はありませんか。
aki_

2020/04/25 11:09

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

退会済みユーザー

2020/04/25 11:58

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問