🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
checkbox

checkboxは、GUIのエレメントです。また、HTML<input>タグのtype属性で扱われる値を指します。

JavaScript

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

Q&A

解決済

2回答

506閲覧

javascript:createElementで作成したチェックボックスへの一括選択機能をつけたい

notsuki

総合スコア7

checkbox

checkboxは、GUIのエレメントです。また、HTML<input>タグのtype属性で扱われる値を指します。

JavaScript

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

0グッド

0クリップ

投稿2023/08/29 16:28

実現したいこと

Javascriptの「createElement」で作成したチェックボックスたちを、
あるボタンを押すことで一括で選択できるようにしたい。

前提

ドットインストールの「javascriptでtodo管理アプリを作ろう」を学びました。
その後、作成したリストたちを一括選択をした上で削除ができる機能をつけたいと思いましたが、うまくいきません。どのようにすれば実現可能でしょうか。

該当のソースコード

<HTML>

<h1> <button id="checkAll">checkAll</button> todoリスト <button id="purge">purge</button> </h1> <div class="todo-container"> <ul id="todos"> <!-- jsのtodoリストが入る --> </ul> </div> <div class="form-container"> <form id="add-form" class="footer"> <input type="text" placeholder="ここにtodoを入力する"> <button>Add</button> </form> </div>
<script.js> let todos; if (localStorage.getItem('todos') === null) { todos = []; } else { todos = JSON.parse(localStorage.getItem('todos')); } const saveTodos = () => { localStorage.setItem('todos', JSON.stringify(todos)); }; const renderTodo = (todo) => { const input = document.createElement('input'); input.type = 'checkbox'; input.checked = todo.isCompleted; input.addEventListener('change', () => { todos.forEach((item) => { if (item.id === todo.id) { item.isCompleted = !item.isCompleted; } }); saveTodos(); }); const span = document.createElement('span'); span.textContent = todo.title; const label = document.createElement('label'); label.appendChild(input); label.appendChild(span); const button = document.createElement('button'); button.textContent = 'x'; button.addEventListener('click', () => { if (!confirm('選択したタスクを削除する?')) { return; } li.remove(); todos = todos.filter((item) => { return item.id !== todo.id; }); saveTodos(); }); const li = document.createElement('li'); li.appendChild(label); li.appendChild(button); document.querySelector('#todos').prepend(li); }; const renderTodos = () => { todos.forEach((todo) => { renderTodo(todo); }); }; document.querySelector('#add-form').addEventListener('submit', (e) => { e.preventDefault(); const input = document.querySelector('#add-form input'); const todo = { id: Date.now(), title: input.value, isCompleted: false, }; renderTodo(todo); todos.push(todo); console.table(todos); saveTodos(); input.value = ''; input.focus(); }) ★★★★★★★★★★★★★ここに、一括選択のコードを書きたいです。★★★★★★★★★★★★ document.querySelector('#purge').addEventListener('click', () => { if (!confirm('選択したリストを削除しますか?')) { return; } todos = todos.filter((todo) => { return todo.isCompleted === false; }); saveTodos(); document.querySelectorAll('#todos li').forEach((li) => { li.remove(); }); renderTodos(); }); renderTodos(); }

試したこと

ベースは、最後の方のコードであるpurgeと同じ要領なのかなと思い、以下のあたりで色々と当てはめてみたのですが、見当違いのものを当てはめているようでエラー(下記)ばかりになってしまいました。。
エラー:◯◯ is undefined, ◯◯ is not a function

document.querySelector('#checkAll').addEventListener('click', () => { todos = todos.filter((todo) => { return todo.isCompleted === false; }); saveTodos(); document.querySelectorAll('#todos li').forEach((li) => { ★この辺りで、「todo.isCompleted === true」になるようなコードがあれば良いのかなと・・・ }); renderTodos(); });

知見のある方がいらっしゃいましたら、ご教授いただけますと幸いです。
どうぞよろしくお願いいたします。

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

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

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

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

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

guest

回答2

0

ベストアンサー

idやclassなどをもう少し意識して設定すると簡潔に書けます
参考までに

javascript

1<script> 2window.addEventListener('DOMContentLoaded', ()=>{ 3 const save=()=>localStorage.setItem('todos',todos.innerHTML); 4 todos.innerHTML=localStorage.getItem('todos'); 5 document.addEventListener('click',({target})=>{ 6 if(target.matches('#add')){ 7 event.preventDefault(); 8 const li=tmp_li.content.cloneNode(true).querySelector('li'); 9 li.querySelector('span').textContent=txt.value; 10 todos.appendChild(li); 11 txt.value=''; 12 save(); 13 } 14 if(target.matches('.del') && confirm('選択したタスクを削除する?')){ 15 target.closest('li').remove(); 16 save(); 17 } 18 if(target.matches('#checkAll')){ 19 document.querySelectorAll('.chk').forEach(x=>x.checked=true); 20 } 21 if(target.matches('#purge') && confirm('選択したリストを削除する?')){ 22 document.querySelectorAll('.chk:checked').forEach(x=>x.closest('li').remove()); 23 save(); 24 } 25 }); 26}); 27 28</script> 29<template id="tmp_li"> 30<li><label><input type="checkbox" class="chk"><span class="val"></span></label><button class="del">x</button></li> 31</template> 32<h1> 33 <button id="checkAll">checkAll</button> 34 todoリスト 35 <button id="purge">purge</button> 36</h1> 37<div class="todo-container"> 38 <ul id="todos"> 39 <!-- jsのtodoリストが入る --> 40 </ul> 41</div> 42 43<div class="form-container"> 44 <form id="add-form" class="footer"> 45 <input id="txt" type="text" placeholder="ここにtodoを入力する"> 46 <button id="add" type="submit">Add</button> 47 </form> 48</div>

※localstorageに保存するのを忘れていたので調整
※エンター対応

投稿2023/08/30 00:23

編集2023/08/30 04:27
yambejp

総合スコア116644

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

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

notsuki

2023/08/30 01:52

丁寧なご回答、大変ありがとうございます。別解もあるのですね。 実際にコードを打ち込んでみたく思います。また、試してみたコメントを追記させていただきます。
yambejp

2023/08/30 01:56 編集

そのままコピペすれば動くようにしてあるので挙動を確認ください
notsuki

2023/08/30 02:23

お返事ありがとうございます。コピペしてみたところ、フォームに書き込んでAddボタンをクリックすると、index.htmlに飛ぶ(ページが更新される?)ような挙動となりました。 何か間違えた場所に貼り付けているのかもしれません。 jsはscript.jsというファイルにまとめているので、一回目はそちらに貼り付け、 2回目はhtmlの</body>の上に貼り付けたのですが、やはりページが更新されているような挙動でした。 もう少しコードをよく読んで試したく思います。ご回答いただきましたのにすみません。
yambejp

2023/08/30 03:25

一旦そのままコピペで動作を確認してください お手持ちのソースとはidやclassの付け方が異なると思いますのでHTMLもまるっとコピペで試してください
notsuki

2023/08/30 04:24

何度もすみません、ありがとうございます。 addができなかったのは、フォームに入力して「Enterキー」を押していたからでした。 以前のコードでは、Enterキー押下か、Addボタン押下かのどちらかでリストに追加されていたため、癖になっておりました。addボタンを押下したところ、うまく動作いたしました。お騒がせして申し訳ありません。 現状はエンターを押下するとフォームに書いたものが消えてしまう為、いただいたコードをよく読んで、Enterキー押下でも入力できるよう、もう少し動作を確認したく思います。 大変お世話になり、ありがとうございました。
yambejp

2023/08/30 04:28

エンターでaddするのですね。 そうなるとaddボタンはサブミットにした方がよく、eventをpreventDefault()すれば実現可能です エンター対応版に書き換えておきました
notsuki

2023/08/30 04:53

ボタンのtypeをsubmitにするとenterで入力可能となるのですね。勉強となりました。ありがとうございます。 いただいたコードで試させていただいたところ、画面内のタスクが表示されていく場所の一番上に、 [] が表示されるようになりました。こちらの左右には、チェックボックスもxボタンもついていませんでした。 配列の入れ物だけが表示されているようなイメージです。 こちらについても、原因を追いかけていこうかと思います。お世話になり、ありがとうございます。
yambejp

2023/08/30 05:03 編集

> 画面内のタスクが表示されていく場所の一番上に、[]が表示されるようになりました ごめんなさい、現象が確認できませんが、何をしたときにそうなりますか? 以下codeにソース上げておきましたのでご確認お願いします https://codepen.io/yambejp/pen/jOXqLre
notsuki

2023/08/30 05:24

お返事ありがとうございます。 シークレットウインドウ(chrome)で試したところ問題ない挙動でしたので、通常のブラウザでキャッシュをクリアしてから確認したところ、[]は消えました。お騒がせして申し訳ありませんでした。 こちらで、私の実現したかった挙動が実現できたことになります。ここまでお付き合いいただけると思っておりませんでしたので、本当に助かりました。あとは、書いていただいたコードをよく見て理解するところから始めたいと思います。お世話になり、ありがとうございました。ベストアンサーとさせてください。 また、いただいたURLへ行き、addボタンを押下したところ以下の文章が表示され、確認まですることができませんでした。ただ、[]はキャッシュの問題だったのかなと思いますので、これ以上はお時間いただかなくて大丈夫です。たくさんお時間いただきすみませんでした。 Referred from Pen todo test What happened? A link in this Pen has a missing `href` value, or this Pen is trying to change the document.location more details Take heart, you can just go back. Refresh the Pen to return to the previous page. ご丁寧に対応していただき、本当にありがとうございました。
yambejp

2023/08/30 05:34 編集

codepenのエラーはちょっとわかりません。 今更ですが、[]については、おそらく私のソースだとULのinnerHTMLをそのままテキストで保存・呼び出しさせる仕組みなので、前に保持していたJSONデータが最初空配列として呼ばれて表示されたのだと思います。その後はなにかするたびにlocalstorageのtodosを上書きしているので、2回目以降は大丈夫なのでしょう
notsuki

2023/08/30 05:52

お返事ありがとうございます。予想される出来事がそうなのですね。 いま、サーバーにアップロードして挙動を確認したところも、[]は現れなかったので心配なさそうです。 細やかなご対応本当にありがとうございました。
guest

0

js

1document.querySelector('#checkAll').addEventListener('click', () => { 2 document.querySelectorAll('#todos input[type=checkbox]').forEach((checkbox) => { 3 checkbox.checked = true; 4 }); 5});

以下のあたりで色々と当てはめてみた

そういうアプローチはやめたほうがよいでしょう。目的のために必要な手順を考え、それをコードにするのがプログラミングです。


追記:
「すべてのアイテムを完了状態にする」が目的なら、以下のようにするのが簡単です。

js

1document.querySelector('#checkAll').addEventListener('click', () => { 2 todos.forEach(item => { item.isCompeted = true; }); 3 saveTodos(); 4 // すべて描き直す。チェックボックスの状態は isCompleted が反映される 5 document.querySelector('#todos').textContent = ''; 6 renderTodos(); 7});

投稿2023/08/29 22:56

編集2023/08/30 04:56
int32_t

総合スコア21668

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

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

notsuki

2023/08/29 23:46

早速のご回答ありがとうございます。 仰る通りかと思います。必要な手順を考えてみてはいるのですが、検討はずれなことが多くお恥ずかしい限りです。int32_2さんの回答を見て、なるほどinput[type = checkbox]であったり、checkbox.checked = trueとすれば良かったのだと学ぶことができ有難いです。まずは教えて頂いたコードを実際に試してみたく思います。
notsuki

2023/08/30 04:31

頂いたコードを試してみたところ、全選択はされるのですが、その後purgeボタンを押すと選択がすべて解除されるという挙動となりました。もう少し試してみたく思います。お世話になり、ありがとうございました。
int32_t

2023/08/30 04:47

本当にやりたいことは「すべてのチェックボックスをチェックする」ではなく「すべての TODO アイテムを完了状態にする」だったのではありませんか? だとすると、この回答では不十分ですね。
notsuki

2023/08/30 04:59

お返事ありがとうございます。 課題の切り分けが不十分で申し訳ありません。 一括選択をして、削除できる挙動をめざしておりましたので、現状、削除のコードまではあるのかと思っておりました為、あとは一括選択をするコードを書けばよいと思っておりました。おっしゃる通り、ただ見た目が選択されたように変わるだけでは不十分で、「一括選択および完了状態(あとはpurgeを押下すれば一括で消せるようになる手前の状態)」になっていることを目指しております。
notsuki

2023/08/30 05:42

お返事ありがとうございます。いただいたコードを試したところ、以下のような挙動となりました。 ・フォームに入力、Addを押下→ページが再読み込みされ、フォームに書いたものが消える 一つ上のブロックのe.preventDefault();が効いていないのでしょうか。原因を探したいと思います。 お時間いただき申し訳ありませんでした。ご丁寧に対応いただき、ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問