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

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

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

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

JavaScript

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

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Q&A

解決済

1回答

264閲覧

【javascript】appendしたセレクトメニューの値が、ユーザーの選択に関わらず同じパラメータを送信してしまう

shanghuifu

総合スコア5

Ruby on Rails

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

JavaScript

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

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

0グッド

0クリップ

投稿2019/12/18 10:28

編集2019/12/18 11:09

実現したいこと

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側で問題が起きていると仮説をたてました。しかし、自分の理解が甘く、検索してもそれらしい記事を見つけられずに行き詰ってしまいました。
何か解決につながるヒントをいただけたら嬉しいです。

補足情報

初めての質問投稿になります。
情報不足や不適切な説明などがあればご指摘いただきたいです。
ご覧になる皆さんにストレスのかからない質問を投稿できるようになりたいので、どうぞよろしくお願いします。

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

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

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

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

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

winterboum

2019/12/18 10:59

「中小のselectorはoptionは無いが初めから存在している」 という理解で合っていますか?
winterboum

2019/12/18 11:00

違うか、一度削除して作りなおしですね。
shanghuifu

2019/12/18 11:06

説明が足らず、失礼しました。 初めからは存在していません。 最初の段階では大分類のセレクタのみ表示されており、ajaxのdoneメソッドでアペンドする際に用意しています。 具体的には「該当のソースコード」の最後のコードブロックに記載してある方法で用意します。 doneメソッドの最後にappendChildrenやappendGrandChildrenという関数を呼び出す中で生成しています。
guest

回答1

0

ベストアンサー

JSは得意ではなく、特にあとから追加した要素の振る舞いは更に苦手なので、識者の回答があるんではと控えていましたが、未だ無いようなので苦手なりの。。

後から追加した要素のclassやidがうまく認識出来ないのによくであいました。
その時とっていた手は、今回のケースでは
予めselectは用意しておいてoptionだけ入れ替える。
中が決まるまで小を見せたくないのなら、displayで対応

あと、もしかすると、ですが
同じname、classの要素がhtmlの後ろの方に隠れていたりしませんか?
後ろの方の値で上書きされてしまってるという可能性は?

投稿2019/12/20 00:06

winterboum

総合スコア23347

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

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

shanghuifu

2019/12/20 05:28

お忙しい中回答いただきありがとうございます! consoleで確認したところ、同じname属性やclass要素は存在しませんでした。 - 予めselectは用意しておいてoptionだけ入れ替える。 - 中が決まるまで小を見せたくないのなら、displayで対応 そして、このやり方で正しくパラメータを送ることができました! ありがとうございます!! ただ、1点だけモヤっとしていまして...。 selectを予め用意するかしないかでどんな違いがあるのでしょうか? 検証ツールで確認すると、コードの記述には違いがありません。 railsとjsの相性なのか、表面上は同じでも実際に処理をする中で違いがあるということなのでしょうか。動かなかったプログラムが動いたので、何か違いがあるのだとは思いますが、気になったので検索しても見つけられませんでした...。 自分の理解が浅く恐縮ですが、その点の仕組みについても教えていただきたいです。
winterboum

2019/12/20 06:10

その違いなぜかわかりません。 識者の登場を待ちたい。
shanghuifu

2019/12/20 06:30

ありがとうございます、そうですね。 回答依頼できる方に依頼を送信しました。
winterboum

2019/12/20 06:37

答えわかったら私にも教えてください
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問