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

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

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

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

Q&A

解決済

1回答

578閲覧

ブラウザをリロードすると、条件分岐で振り分けた<li>タグが、1箇所にまとまってしまうのを直したい。

oil

総合スコア11

JavaScript

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

0グッド

0クリップ

投稿2021/12/18 19:29

編集2022/01/15 03:02

前提・実現したいこと

ブラウザをリロードすると、振り分けた<li>タグが1っ箇所にまとまってしまうのを直したい。

発生している問題・エラーメッセージ

JavaScriptで、

TODOリストにラジオボタンで4つの条件分岐を付けて、

4つの<ul>に、appendChild(li);で<li>タグを追加して、

振り分けをした状態のままの保存方法がどうすれば良いのか分かりません。

現状は、document.querySelectorAll("li");で、

<li>タグがまとめて保存されてしまいます。

querySelectorAll("li");をどう変えれば良いのか教えて下さい。

よろしくお願いします。

該当のソースコード

JavaScript

1const form = document.getElementById("form"); 2const input = document.getElementById("input"); 3const ul_0 = document.getElementById("ul_0"); 4const ul_1 = document.getElementById("ul_1"); 5const ul_2 = document.getElementById("ul_2"); 6const ul_3 = document.getElementById("ul_3"); 7const all_radio = document.getElementById("all_radio"); 8 9// ローカルデータ読み込み 10let todos = JSON.parse(localStorage.getItem("todos")); 11if (todos) { 12 // 配列の全要素に対して反復処理 13 todos.forEach((todo) => { 14 add(todo); 15 }); 16} 17// フォームがエンター(submit)された時処理 18form.addEventListener("submit", function (event) { 19 // デフォルトのイベント中止(エンター後のリロード) 20 event.preventDefault(); 21 // 下記の関数submit後に行いたい処理 22 add(); 23}); 24 25function add(todo) { 26 // フォームに入力された値を取る 27 let todoText = input.value; 28 29 if (todo) { 30 todoText = todo.text; 31 } 32 // フォームが空の状態でのliタグの追加を防ぐ 33 if (todoText.length > 0) { 34 // liタグの作成 35 const li = document.createElement("li"); 36 // liにフォームに入力された値を入れる 37 li.innerText = todoText; 38 // liタグにlist-group-itemクラスの追加、デザインの為 39 li.classList.add("list-group-item"); 40 41 // ラジオボタンの選択された値 42 let radioNodeList = all_radio.deadline; 43 let radiobtn = radioNodeList.value; 44 45 switch (radiobtn) { 46 case "0": 47 // ul_0の子要素として追加する 48 ul_0.appendChild(li); 49 // フォームを空にする 50 input.value = ""; 51 // ローカルストレージに保存する 52 saveDate(); 53 break; 54 case "1": 55 ul_1.appendChild(li); 56 input.value = ""; 57 saveDate(); 58 break; 59 case "2": 60 ul_2.appendChild(li); 61 input.value = ""; 62 saveDate(); 63 break; 64 case "3": 65 ul_3.appendChild(li); 66 input.value = ""; 67 saveDate(); 68 } 69 70 if (todo && todo.completed) { 71 li.classList.add("text-decoration-line-through"); 72 } 73 74 li.addEventListener("contextmenu", function (event) { 75 // 右クリックイベントブロック 76 event.preventDefault(); 77 li.remove(); 78 saveDate(); 79 }); 80 81 li.addEventListener("click", function () { 82 li.classList.toggle("text-decoration-line-through"); 83 saveDate(); 84 }); 85 } 86} 87// li要素を取得して、配列としてまとめておく 88function saveDate() { 89 const lists = document.querySelectorAll("li"); 90 // 空の配列を定義 91 const todos = []; 92 93 // 配列の全要素に対して反復処理 94 lists.forEach((li) => { 95 // todosの配列に追加していく処理 96 todos.push({ 97 // 入力された値 98 text: li.innerText, 99 completed: li.classList.contains("text-decoration-line-through"), 100 }); 101 }); 102 // jsonでローカルデータ保存 103 localStorage.setItem("todos", JSON.stringify(todos)); 104} 105 106// リセットボタン 107const Reset = document.getElementById("Reset"); 108 109Reset.addEventListener("click", function () { 110 // 子要素全消去 111 all_ul.innerHTML = ""; 112 window.location.reload(); 113 saveDate(); 114}); 115

HTML

1<!DOCTYPE html> 2<html lang="ja"> 3 <head> 4 <meta charset="UTF-8" /> 5 <meta http-equiv="X-UA-Compatible" content="IE=edge" /> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 7 8 <!-- CSS --> 9 <link 10 href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" 11 rel="stylesheet" 12 integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" 13 crossorigin="anonymous" 14 /> 15 16 <title>条件分岐の練習</title> 17 </head> 18 <body class="bg-light"> 19 <div class="container w-100"> 20 <h1 class="text-center text-info my-4">納期管理アプリ</h1> 21 22 <form id="all_radio"> 23 <div class="responsibility"> 24 <div class="form-check"> 25 <input 26 class="form-check-input" 27 type="radio" 28 name="deadline" 29 id="t_t" 30 value="0" 31 checked 32 /> 33 <label class="form-check-label" for="flexRadioDefault2"> 34 通常業務、通常配送 35 </label> 36 </div> 37 <div class="form-check"> 38 <input 39 class="form-check-input" 40 type="radio" 41 name="deadline" 42 id="t_k" 43 value="1" 44 /> 45 <label class="form-check-label" for="flexRadioDefault1"> 46 通常業務、緊急配送 47 </label> 48 </div> 49 </div> 50 51 <div class="deadline mt-3"> 52 <div class="form-check"> 53 <input 54 class="form-check-input" 55 type="radio" 56 name="deadline" 57 id="j_t" 58 value="2" 59 /> 60 <label class="form-check-label" for="flexRadioDefault2"> 61 重要業務、通常配送 62 </label> 63 </div> 64 <div class="form-check"> 65 <input 66 class="form-check-input" 67 type="radio" 68 name="deadline" 69 id="j_k" 70 value="3" 71 /> 72 <label class="form-check-label" for="flexRadioDefault1"> 73 重要業務、緊急配送 74 </label> 75 </div> 76 </div> 77 </form> 78 79 <form id="form" class="mt-2 mb-5"> 80 <input 81 id="input" 82 class="form-control" 83 placeholder="納期、送り先を入力" 84 autocomplete="off" 85 /> 86 </form> 87 88 <div id="all_ul" class="f-container"> 89 <ul class="list-group text-secondary" id="ul_3"> 90 重要、緊急 91 </ul> 92 <ul class="list-group text-secondary" id="ul_2"> 93 重要、通常 94 </ul> 95 <ul class="list-group text-secondary" id="ul_1"> 96 通常、緊急 97 </ul> 98 <ul class="list-group text-secondary" id="ul_0"> 99 通常、通常 100 </ul> 101 </div> 102 </div> 103 104 <!-- Resetボタン --> 105 <div class="d-grid gap-2 col-1 mx-auto pt-5"> 106 <button id="Reset" class="btn btn-primary" type="button">Reset</button> 107 </div> 108 109 <script src="todo.js"></script> 110 </body> 111</html> 112

試したこと

追加する<li>タグに.classNameでクラスの追加や、

querySelectorで、<ul>タグを保存しようとしましたが、

上手くいきませんでした。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

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

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

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

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

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

m.ts10806

2021/12/18 22:08

>前提・実現したいこと など、質問テンプレートのままのように思います。 なるべく埋められた方がアドバイスも得やすくなります。
oil

2021/12/19 03:14

アドバイスありがとうございます。 今後は、気をつけます。
m.ts10806

2021/12/19 03:25

質問は編集できるので今からでも
oil

2021/12/19 04:15

編集したのですが反映されてませんでした。
guest

回答1

0

ベストアンサー

詳しく試していませんが・・・。

勝手ですが saveDate を saveData に直しました

js

1function saveData() { 2 const lists = document.querySelectorAll("li"); 3 // 空の配列を定義 4 const todos = { }; 5 // 配列の全要素に対して反復処理 6 lists.forEach((li) => { 7 // todosの配列に追加していく処理 8 let parent = li.parentNode, id = parent.id; 9 if (id) { 10 if (! todos[id]) 11 todos[id] = [ ]; 12 13 todos[id].push ({ 14 // 入力された値 15 text: li.innerText, 16 completed: li.classList.contains("text-decoration-line-through"), 17 }); 18 } 19 }); 20 // jsonでローカルデータ保存 21 localStorage.setItem("todos", JSON.stringify(todos)); 22} 23 24function loadData () { 25 let todos = JSON.parse(localStorage.getItem("todos")); 26 if (! todos) 27 return; 28 29 let LI = document.createElement ('li'); 30 LI.classList.add ("list-group-item"); 31 32 for (let [id, group] of Object.entries (todos)) { 33 let ul = document.getElementById (id); 34 if (ul){ 35 for (let {text, completed} of group) { 36 let li = LI.cloneNode (false); 37 li.textContent = text; 38 if (completed) 39 li.classList.add("text-decoration-line-through"); 40 ul.appendChild (li); 41 } 42 } 43 } 44} 45

>出来ませんでした

危うく消すところでした。
テストに使ったコードです。

関数 add が機能を兼用しているのがダメですよ

html&js

1<!DOCTYPE html> 2<html lang="ja"> 3 <head> 4 <meta charset="UTF-8" /> 5 <meta http-equiv="X-UA-Compatible" content="IE=edge" /> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 7 8 <!-- CSS --> 9 <link 10 href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" 11 rel="stylesheet" 12 integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" 13 crossorigin="anonymous" 14 /> 15 16 <title>条件分岐の練習</title> 17 </head> 18 <body class="bg-light"> 19 <div class="container w-100"> 20 <h1 class="text-center text-info my-4">納期管理アプリ</h1> 21 22 <form id="all_radio"> 23 <div class="responsibility"> 24 <div class="form-check"> 25 <input 26 class="form-check-input" 27 type="radio" 28 name="deadline" 29 id="t_t" 30 value="0" 31 checked 32 /> 33 <label class="form-check-label" for="flexRadioDefault2"> 34 通常業務、通常配送 35 </label> 36 </div> 37 <div class="form-check"> 38 <input 39 class="form-check-input" 40 type="radio" 41 name="deadline" 42 id="t_k" 43 value="1" 44 /> 45 <label class="form-check-label" for="flexRadioDefault1"> 46 通常業務、緊急配送 47 </label> 48 </div> 49 </div> 50 51 <div class="deadline mt-3"> 52 <div class="form-check"> 53 <input 54 class="form-check-input" 55 type="radio" 56 name="deadline" 57 id="j_t" 58 value="2" 59 /> 60 <label class="form-check-label" for="flexRadioDefault2"> 61 重要業務、通常配送 62 </label> 63 </div> 64 <div class="form-check"> 65 <input 66 class="form-check-input" 67 type="radio" 68 name="deadline" 69 id="j_k" 70 value="3" 71 /> 72 <label class="form-check-label" for="flexRadioDefault1"> 73 重要業務、緊急配送 74 </label> 75 </div> 76 </div> 77 </form> 78 79 <form id="form" class="mt-2 mb-5"> 80 <input 81 id="input" 82 class="form-control" 83 placeholder="納期、送り先を入力" 84 autocomplete="off" 85 /> 86 </form> 87 88 <div id="all_ul" class="f-container"> 89 <ul class="list-group text-secondary" id="ul_3"> 90 重要、緊急 91 </ul> 92 <ul class="list-group text-secondary" id="ul_2"> 93 重要、通常 94 </ul> 95 <ul class="list-group text-secondary" id="ul_1"> 96 通常、緊急 97 </ul> 98 <ul class="list-group text-secondary" id="ul_0"> 99 通常、通常 100 </ul> 101 </div> 102 </div> 103 104 <!-- Resetボタン --> 105 <div class="d-grid gap-2 col-1 mx-auto pt-5"> 106 <button id="Reset" class="btn btn-primary" type="button">Reset</button> 107 </div> 108 109 <script> 110const form = document.getElementById("form"); 111const input = document.getElementById("input"); 112const ul_0 = document.getElementById("ul_0"); 113const ul_1 = document.getElementById("ul_1"); 114const ul_2 = document.getElementById("ul_2"); 115const ul_3 = document.getElementById("ul_3"); 116const all_radio = document.getElementById("all_radio"); 117 118loadData (); 119// ローカルデータ読み込み 120/* 121let todos = JSON.parse(localStorage.getItem("todos")); 122if (todos) { 123 // 配列の全要素に対して反復処理 124 todos.forEach((todo) => { 125 add(todo); 126 }); 127} 128*/ 129// フォームがエンター(submit)された時処理 130form.addEventListener("submit", function (event) { 131 // デフォルトのイベント中止(エンター後のリロード) 132 event.preventDefault(); 133 // 下記の関数submit後に行いたい処理 134 add(); 135}); 136 137function add(todo) { 138 // フォームに入力された値を取る 139 let todoText = input.value; 140 141 if (todo) { 142 todoText = todo.text; 143 } 144 // フォームが空の状態でのliタグの追加を防ぐ 145 if (todoText.length > 0) { 146 // liタグの作成 147 const li = document.createElement("li"); 148 // liにフォームに入力された値を入れる 149 li.innerText = todoText; 150 // liタグにlist-group-itemクラスの追加、デザインの為 151 li.classList.add("list-group-item"); 152 153 // ラジオボタンの選択された値 154 let radioNodeList = all_radio.deadline; 155 let radiobtn = radioNodeList.value; 156 157 switch (radiobtn) { 158 case "0": 159 // ul_0の子要素として追加する 160 ul_0.appendChild(li); 161 // フォームを空にする 162 input.value = ""; 163 // ローカルストレージに保存する 164 saveData(); 165 break; 166 case "1": 167 ul_1.appendChild(li); 168 input.value = ""; 169 saveData(); 170 break; 171 case "2": 172 ul_2.appendChild(li); 173 input.value = ""; 174 saveData(); 175 break; 176 case "3": 177 ul_3.appendChild(li); 178 input.value = ""; 179 saveData(); 180 } 181 182 if (todo && todo.completed) { 183 li.classList.add("text-decoration-line-through"); 184 } 185 186 li.addEventListener("contextmenu", function (event) { 187 // 右クリックイベントブロック 188 event.preventDefault(); 189 li.remove(); 190 saveDate(); 191 }); 192 193 li.addEventListener("click", function () { 194 li.classList.toggle("text-decoration-line-through"); 195 saveDate(); 196 }); 197 } 198} 199// li要素を取得して、配列としてまとめておく 200function saveData() { 201 const lists = document.querySelectorAll("li"); 202 // 空の配列を定義 203 const todos = { }; 204 // 配列の全要素に対して反復処理 205 lists.forEach((li) => { 206 // todosの配列に追加していく処理 207 let parent = li.parentNode, id = parent.id; 208 if (id) { 209 if (! todos[id]) 210 todos[id] = [ ]; 211 212 todos[id].push ({ 213 // 入力された値 214 text: li.innerText, 215 completed: li.classList.contains("text-decoration-line-through"), 216 }); 217 } 218 }); 219 // jsonでローカルデータ保存 220 localStorage.setItem("todos", JSON.stringify(todos)); 221} 222 223function loadData () { 224 let todos = JSON.parse(localStorage.getItem("todos")); 225 if (! todos) 226 return; 227 228 let LI = document.createElement ('li'); 229 LI.classList.add ("list-group-item"); 230 231 for (let [id, group] of Object.entries (todos)) { 232 let ul = document.getElementById (id); 233 if (ul){ 234 for (let {text, completed} of group) { 235 let li = LI.cloneNode (false); 236 li.textContent = text; 237 if (completed) 238 li.classList.add("text-decoration-line-through"); 239 ul.appendChild (li); 240 } 241 } 242 } 243} 244 245// リセットボタン 246const Reset = document.getElementById("Reset"); 247 248Reset.addEventListener("click", function () { 249 // 子要素全消去 250 all_ul.innerHTML = ""; 251 window.location.reload(); 252 saveDate(); 253}); 254 255input.addEventListener ('change', function () { 256 add(); 257}, false); 258 259 </script> 260 </body> 261</html>

投稿2021/12/19 00:39

編集2021/12/19 05:19
babu_babu_baboo

総合スコア616

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

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

oil

2021/12/19 03:12

回答ありがとうございます。 今から試してみます。
oil

2021/12/19 04:55 編集

出来ませんでした。 まだ自分が出来るレベルの問題では無さそうなので、 もう少し勉強してから試してみます。 ご回答ありがとうございました。
babu_babu_baboo

2021/12/19 05:28

input要素の値に変化があった場合、追加保存される仕様です
oil

2021/12/19 11:48

完成させる事が出来ました。 本当にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問