実現したいこと
削除ボタンを押した際に削除ボタンを含んだ部分のフォーム(削除ボタンの親ノード)が削除されることをゴールとしております。
発生している問題・分からないこと
現在は削除ボタンを押した際に、該当フォームではなく、一番下のフォームが削除されるエラーとなっております。
例)3個フォームを追加した際に2個目の削除を押すと2個目のフォームが削除されることが理想だが3個目のフォームが削除される。
追加するフォームのテンプレートはjavascript内でテンプレートリテラルで囲っており、追加ボタンを押すと画面下にフォームが追加できる様に実装しております。
フォームの追加動画
該当のソースコード
new.html.erb
1<header class="ms-4 col-12"> 2 <%= render "shared/header" %> 3<header> 4<body> 5 <div id="customers" data-customers="<%= @customers.to_json %>"></div> 6 <br> 7 <h1 class="ms-4">新規日報作成</h1> 8 <br> 9 <!-- 追加ボタンの実装 --> 10 <button id="add">追加</button> 11 <!-- 日報フォーム部分の実装 --> 12 <%= form_with model: @report, local:true do |f| %> 13 <!-- 日報テンプレート部分 --> 14 <%= f.fields_for :report_details, @report.report_details.build do |report_detail| %> 15 16 <% end %> 17 <!-- 日報詳細テンプレート部分はここまで --> 18 <!-- 日報詳細追加フィールド --> 19 <div id="add-field"> 20 </div> 21 <div> 22 日報日付 23 <%= f.datetime_field :date, class:"mt-4", id:"report-date" %> 24 </div> 25 <div> 26 <%= f.hidden_field :employee_id, :value => current_employee.id %> 27 </div> 28 <div> 29 <%= f.submit '登録', class: 'mt-4' %> 30 </div> 31 <% end %> 32 <!-- 日報フォーム部分はここまで --> 33</body>
add_element.js
1window.addEventListener('DOMContentLoaded', function() { 2 //追加ボタンの取得 3 let add = document.getElementById("add"); 4 //追加先の取得 5 let addField = document.getElementById("add-field"); 6 //得意先情報の取得 7 let searchTargets = $('#customers').data('customers'); 8 9 10 var x = 0; 11 12 13 14 15 add.addEventListener('click', function() { 16 x++; 17 //フォーム追加部分 18 var formHtml = ` 19 <div id="field"> 20 <div> 21 <div id="search-view" > 22 <input type="text" id="search-input" placeholder="得意先を検索"> 23 <div id="test"> 24 </div> 25 </div> 26 <div id="result-view" class="mt-2"> 27 得意先名 28 <input type="text" id="report-detail-customer" name="report[report_details_attributes][${x}][customer_id]"> 29 今回の内容 30 <input type="text" id="report-detail-content" name="report[report_details_attributes][${x}][content]"> 31 次回の目標 32 <input type="text" id="report-detail-plan" name="report[report_details_attributes][${x}][plan]"> 33 </div> 34 </div> 35 <div id="delete">削除</div> 36 </div> 37 `; 38 //フォーム要素の追加 39 $(addField).append(formHtml); 40 41 42 //追加ボタンがされた際に各要素を取得 43 //検索欄の全取得 44 let searchInputs = document.querySelectorAll("#search-input"); 45 //検索結果親要素の全取得 46 let results = document.querySelectorAll("#test"); 47 //日報詳細欄の全取得 48 let reportDetails = document.querySelectorAll("#report-details-content") 49 //日報詳細の得意先名欄の取得 50 let roportDetailCustomers = document.querySelectorAll("#report-detail-customer"); 51 //フォームフィールドの取得 52 let fields = document.querySelectorAll("#field"); 53 //削除ボタンの全取得 54 let deletes = document.querySelectorAll("#delete"); 55 56 57 58 //検索欄それぞれの処理 59 searchInputs.forEach(function(search) { 60 //検索欄に文字入力された際の処理 61 search.addEventListener("input", function() { 62 console.log("テスト"); 63 for (let i = 0; i < results.length; i++) { 64 //再度検索欄の全取得 65 let inputs = document.querySelectorAll("#search-input"); 66 //入力された文字の取得 67 let inputsValue = inputs[i].value.trim().toLowerCase(); 68 //検索結果表示欄の親情報の取得 69 let result = results[i]; 70 //日報詳細の得意先名欄の取得 71 let roportDetailCustomer = roportDetailCustomers[i]; 72 //検索結果を挿入する配列を作成 73 let array = [] 74 //入力された文字が得意先にマッチするかの処理 75 searchTargets.forEach((target) => { 76 //一度検索結果を全削除 77 let deleteName = document.querySelectorAll("#test-child"); 78 let deleteId = document.querySelectorAll("#customer-id"); 79 deleteName.forEach((name) => { 80 name.remove(); 81 }); 82 deleteId.forEach((id) => { 83 id.remove(); 84 }); 85 //検索欄が空欄の際の処理 86 if(!inputsValue) { 87 let newElement = document.createElement('div'); 88 newElement.setAttribute("id","test-child"); 89 newElement.innerHTML = "検索欄が空欄です"; 90 result.appendChild(newElement); 91 92 //入力された文字と得意先名がマッチした際の処理 93 } else if(target.name.includes(inputsValue)) { 94 array.push(target); 95 for (let i =0; i < array.length; i++) { 96 //検索結果の子情報を作成 97 let newEle = document.createElement('div'); 98 let customerId = document.createElement('div'); 99 //検索結果の子情報に命名 100 newEle.setAttribute("id","test-child"); 101 customerId.setAttribute("id","customer-id"); 102 //検索結果の子情報に値を挿入 103 newEle.innerHTML = array[i].name; 104 customerId.innerHTML = array[i].id; 105 customerId.style.display = 'none'; 106 //検索結果の子情報を表示 107 result.appendChild(newEle); 108 result.appendChild(customerId); 109 //検索結果の子情報を全取得 110 let customerNameAll = document.querySelectorAll("#test-child"); 111 let customerIdAll = document.querySelectorAll("#customer-id"); 112 //検索結果の子情報がクリックされた際の処理 113 for (let n=0; n < customerNameAll.length; n++) { 114 //クリックされた子情報を日報明細に挿入 115 customerNameAll[n].addEventListener('click', function() { 116 roportDetailCustomer.value = customerIdAll[n].innerHTML; 117 newEle.style.display = 'none'; 118 }); 119 }; 120 }; 121 }; 122 }); 123 }; 124 }); 125 }); 126 //検索欄から日報明細への登録の処理ここまで 127 128 //削除機能の実装 129 deletes.forEach(function(dlt) { 130 let parent = dlt.parentNode 131 dlt.addEventListener("click", function() { 132 parent.remove(); 133 }); 134 }); 135 //削除機能の実装はここまで 136 }); 137});
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
①フォームが追加された際に追加部分を削除ボタンを全取得。
②全取得した削除ボタンをForEach文で繰り返し処理を行う。
③削除ボタンの親ノード(該当フォーム部分)を取得。
④削除ボタンを押した際に親ノード(該当フォーム部分)を削除
色々調べ、上記4つの手順で実装したのですが、思うような挙動にならず、苦戦している所となります。
補足
現在プログラミング学習中の為、文章不十分の可能性がございます。
追記した方が良い文章、コード等あればコメントいただけますと幸いです。