実現したいこと
railsを用いて、フリマアプリを開発しています。
商品を出品するフォームの一部にカテゴリを選択する箇所があり、そこをjsで実装しています。
実現したいことは、出品フォームを送信すると、ユーザーが選んだカテゴリの値をその他の情報と共にDBに保存することです。
データの流れ
前提)カテゴリには大分類→中分類→小分類があり、railsのgemである"ancestry"を使って管理しています。また、カテゴリはDBに予め登録してあります。なお、大分類はrailsのviewで用意しており、formヘルパーのcollection_selectを用いて実装しています。
①ユーザーが大分類を選択
②ajaxで選択した大分類に属する中分類のカテゴリ名とidを取得
③取得した中分類のidと名前を用いてoptionを生成(categoryOption)
④生成した複数のoptionを、予め用意したselectタグと共にappnedする
⑤これを大分類→中分類、中分類→小分類で行う
⑥実際に保存するデータは小分類カテゴリのidのみ
ancestryの仕様に合わせ、小分類のカテゴリidのみ保存します。
発生している問題・エラーメッセージ
エラー自体は発生していません。
しかし、SUBMITをした後のパラメーターを確認すると、ユーザーの選択に関係なくアペンドしたselectタグの先頭のカテゴリidが送信されています。
以下、binding.pryで確認した際の該当部分になります。
"item"=>{"name"=>"", "text"=>"", "category_id"=>"33", "condition"=>"", "shipping_fee"=>"", "shipping_from"=>"", "shipping_date"=>"", "price"=>""
3つ目のパラメーター"category_id"に33が入っていますが、これはappendした選択肢の先頭の値になっています。実際には他の値を選択しているので、本来であれば35など他の値が入るはずです。
該当のソースコード
optionを生成するコードは以下の通りです。
中分類以下のカテゴリはajaxで配列として返されるので、forEachでこの処理を繰り返しています。
生成したoptionはcategoryOptionsという変数に代入していきます。
js
1children.forEach(function(child){ 2 categoryOptions += createOption(child); 3 });
js
1function createOption(category){ 2 var option = `<option value="${category.id}">${category.name}</option>`; 3 return option; 4 }
そして、選択肢を複数持ったcategoryOptionsを引数として渡してselect全体を生成し、ページにappendします。
js
1function appendChildren(categoryOptions){ 2 var childSelector = ''; 3 childSelector = `<div class="child-category"> 4 <select id="child-category" name="item[category_id]"> 5 ${categoryOptions} 6 </select> 7 </div>`; 8 $('.form-box__select').append(childSelector) 9 }
全体のコード
説明に不備があるかもしれないので、該当の処理を行うjsのコード全体も添付いたします。
js
1$(document).on('turbolinks:load', function(){ 2 $(function(){ 3 // 大分類選択時のイベント処理 4 $('#parent-category').on('change', function(){ 5 var parent_id = $('#parent-category').val(); 6 if (parent_id != ''){ 7 $.ajax({ 8 type: 'GET', 9 url: '/items/get_children', 10 data: { parent_id: parent_id }, 11 dataType: 'JSON' 12 }) 13 .done(function(children){ 14 $('.child-category').remove(); 15 var categoryOptions = ''; 16 children.forEach(function(child){ 17 categoryOptions += createOption(child); 18 }); 19 appendChildren(categoryOptions); 20 }) 21 .fail(function(){ 22 alert('カテゴリーを取得できませんでした') 23 }) 24 }else{ 25 $('.child-category').remove(); 26 $('.grandchild-category').remove(); 27 } 28 }); 29 // 中分類選択時のイベント処理 30 $('.form-box__select').on('change', '#child-category', function(){ 31 var child_id = $('#child-category').val(); 32 if (child_id != ''){ 33 $.ajax({ 34 type: 'GET', 35 url: '/items/get_grandchildren', 36 data: { child_id: child_id }, 37 dataType: 'JSON' 38 }) 39 .done(function(grandchildren){ 40 if (grandchildren.length != 0) { 41 $('.grandchild-category').remove(); 42 var categoryOptions = ''; 43 grandchildren.forEach(function(grandchild){ 44 categoryOptions += createOption(grandchild); 45 }); 46 appendGrandChildren(categoryOptions); 47 } 48 }) 49 .fail(function(){ 50 alert('カテゴリーを取得できませんでした') 51 }) 52 }else{ 53 $('.grandchild-category').remove(); 54 } 55 }); 56 // select内のoptionを生成 57 function createOption(category){ 58 var option = `<option value="${category.id}">${category.name}</option>`; 59 return option; 60 } 61 // 中分類のselectを生成 62 function appendChildren(categoryOptions){ 63 var childSelector = ''; 64 childSelector = `<div class="child-category"> 65 <select id="child-category" name="item[category_id]"> 66 ${categoryOptions} 67 </select> 68 </div>`; 69 $('.form-box__select').append(childSelector) 70 } 71 // 小分類のselectを生成 72 function appendGrandChildren(categoryOptions){ 73 var grandchildSelector = ''; 74 grandchildSelector = `<div class="grandchild-category"> 75 <select id="grandchild-category" name="item[category_id]"> 76 ${categoryOptions} 77 </select> 78 </div>`; 79 $('.form-box__select').append(grandchildSelector) 80 } 81 }); 82});
試したこと
デバッグやコードの変更を試した結果、わかっていることは以下の通りです。
①ajaxやappendは正常に動作する
②パラメータ自体は正常に送信される
③パラメータの値はユーザーの変更に関わらず先頭の選択肢の値が入る
④ajaxを行わず大分類だけで送信すれば、ユーザーの選択に伴い値が変わる
⑤小分類まで入力し送信すると、先頭の値を受け取る
⑥中分類にname属性を追加し、小分類のappendを行わずに送信しても、先頭の値が入る
⑦大分類と中分類、小分類の記述はクラス名等を除いて全て同じ(検証ツールで確認)
⑧小分類の選択時にはユーザーの選択通りの値が入っている(debuggerで確認)
これらの事から原因はフロントサイドで、特に④⑤⑥の事からjs側で問題が起きていると仮説をたてました。しかし、自分の理解が甘く、検索してもそれらしい記事を見つけられずに行き詰ってしまいました。
何か解決につながるヒントをいただけたら嬉しいです。
補足情報
初めての質問投稿になります。
情報不足や不適切な説明などがあればご指摘いただきたいです。
ご覧になる皆さんにストレスのかからない質問を投稿できるようになりたいので、どうぞよろしくお願いします。
回答1件
あなたの回答
tips
プレビュー