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

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

新規登録して質問してみよう
ただいま回答率
85.34%
Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

JavaScript

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

Q&A

1回答

247閲覧

javascriptを利用して動的にフォームが削除ができる様にしたい

takuya-siro

総合スコア7

Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

JavaScript

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

0グッド

1クリップ

投稿2024/12/02 13:59

実現したいこと

削除ボタンを押した際に削除ボタンを含んだ部分のフォーム(削除ボタンの親ノード)が削除されることをゴールとしております。

発生している問題・分からないこと

現在は削除ボタンを押した際に、該当フォームではなく、一番下のフォームが削除されるエラーとなっております。
例)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つの手順で実装したのですが、思うような挙動にならず、苦戦している所となります。

補足

現在プログラミング学習中の為、文章不十分の可能性がございます。
追記した方が良い文章、コード等あればコメントいただけますと幸いです。

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

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

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

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

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

Lhankor_Mhy

2024/12/03 00:31

header 要素が body 要素の外にありませんか? もしそうなら、文法違反です。
Lhankor_Mhy

2024/12/03 00:35 編集

ご提示のコードを可能な限り再現して試してみましたが、『3個フォームを追加した際に2個目の削除を押すと2個目のフォームが削除されることが理想だが3個目のフォームが削除される』という問題は発生しませんでした。2個目の削除ボタンを押すと、2個目の、押した削除ボタンが含まれるフォーム群が削除されます。 ご提示いただいていない部分に原因がありそうです。 問題が再現するコードを(こちらで同じものを確認できるコードを)ご提示ください。
guest

回答1

0

おなじidを付加して、idをつかってHTMLをつかもとうしていませんか?
原則同じページ内に同じidは指定できません。
自分を含む特定のDOMを指定する場合closestをつかってください

html

1<script> 2document.addEventListener('click', ({target})=>{ 3 if(target.matches('.btn')){ 4 target.closest('.parent').remove(); 5 } 6}); 7</script> 8<div class="parent"> 9<input type="button" value="1" class="btn"> 10</div> 11<div class="parent"> 12<input type="button" value="2" class="btn"> 13</div> 14<div class="parent"> 15<input type="button" value="3" class="btn"> 16</div>

投稿2024/12/03 00:14

編集2024/12/03 00:16
yambejp

総合スコア116921

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.34%

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

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

質問する

関連した質問