8800


親カテゴリと子カテゴリがあり、子カテゴリはAjax通信で動的に変わります。  
validateエラーで差し戻された場合に、選択したカテゴリが未選択状態に戻ってしまうのですが  
なぜでしょうか

### View

[code]

    <%= f.select :category_id, options_for_select(categories.collect { |category|
    [category.name, category.id.to_s] }),  {:include_blank =>  'plz select' },
    { id: 'category_select', class: 'form-control select select-default' } %>
    
    <%= f.select :sub_category_id, options_for_select(sub_categories.collect { |child|
    [child.name, child.id] }), {:include_blank =>  'plz select' },
    { id: 'sub_category_select' , class: 'form-control select select-default '} %>
    
[/code]

### JavaScript

[code]

    $(document).on('change', '#category_select', function(evt) {
        $.ajax({
            type: 'GET',
            url: '/items/list',
            dataType: 'json',
            data: {
                category_id: $("#category_select option:selected").val()
            },
            error: function(jqXHR, textStatus, errorThrown) {
                console.log("AJAX Error: " + textStatus);
            },
            success: function(data, textStatus, jqXHR) {
                $("#sub_category_select").empty();
                if (data.length == 0) {
                    $("#sub_category_select").hide();
                } else {
                    $("#sub_category_select").show();
                }
                $.each(data, function(idx, sub) {
                    // console.log("" + item.code + ":" + item.name);
                    $("#sub_category_select").append('<option value="' + sub.id + '">' + sub.name + '</option>');
                });
                console.log("Dynamic country select OK!");
            }
        });
    });
    
[/code]

### Log

[code]

    Started POST "/items" for 127.0.0.1 at 2015-04-06 14:47:05 +0900
    Processing by ItemsController#create as HTML
      Parameters: {"utf8"=>"✓", "authenticity_token"=>"xm/qEvY8bH8JkkqNnOZ5XZgAxVCZLezaNSgYT4tVGLU=", "item"=>{"category_id"=>"280649686", "sub_category_id"=>"122837488", "picture_1_cache"=>"", "picture_2_cache"=>"", "picture_3_cache"=>"", "picture_4_cache"=>"", "title"=>"", "content"=>"", "condition_id"=>"963362593", "delivery"=>"false", "area"=>"1", "limit_day"=>""}, "commit"=>"送信"}
      User Load (0.2ms)  SELECT  "users".* FROM "users"  WHERE "users"."deleted_at" IS NULL AND "users"."id" = 1  ORDER BY "users"."id" ASC LIMIT 1
      Category Load (0.1ms)  SELECT  "categories".* FROM "categories"  WHERE "categories"."id" = ? LIMIT 1  [["id", 1]]
      Category Load (0.1ms)  SELECT "categories".* FROM "categories"  WHERE "categories"."parent_id" = ?  [["parent_id", 1]]
      Category Load (0.4ms)  SELECT "categories".* FROM "categories"  WHERE "categories"."parent_id" IN (8375840, 34598291, 239096215, 280649686, 607038821, 692953909, 738355766, 832268406, 917391766, 959348699)
       (0.1ms)  begin transaction
       (0.1ms)  rollback transaction
      Condition Load (0.2ms)  SELECT "conditions".* FROM "conditions"
      Rendered items/_form.html.erb (8.2ms)
      Rendered pages/_precautions.html.erb (0.1ms)
      Rendered pages/_business_day.html.erb (0.1ms)
      Rendered pages/_privacy_policy.html.erb (0.1ms)
      Rendered items/new.html.erb within layouts/application (11.0ms)
      Todo Load (0.2ms)  SELECT "todos".* FROM "todos"  WHERE ((exhibitor_id = 1 AND status = 'f') OR (proprietor_id = 1 AND status = 'f'))
       (0.1ms)  SELECT COUNT(*) FROM "todos"  WHERE ((exhibitor_id = 1 AND status = 'f') OR (proprietor_id = 1 AND status = 'f'))
      Notification Load (0.2ms)  SELECT "notifications".* FROM "notifications"  WHERE "notifications"."recipient_id" = 1 AND "notifications"."status" = 'f'
      Profile Load (0.2ms)  SELECT  "profiles".* FROM "profiles"  WHERE "profiles"."user_id" = ? LIMIT 1  [["user_id", 1]]
      Rendered ideas/_form.html.erb (0.8ms)
    Completed 200 OK in 52ms (Views: 26.1ms | ActiveRecord: 1.7ms)
    
[/code]

### Controller

[code]

      def new
        @item = current_user.items.build
      end
    
      def create
        @item = current_user.items.build(item_params)
        respond_to do |format|
          if @item.save
            format.html { redirect_to @item, notice: 'アイテムを登録しました' }
    
            format.json { render :show, status: :created, location: @item }
          else
    
            format.html { render :new }
            format.json { render json: @item.errors, status: :unprocessable_entity }
          end
        end
      end
    
      def list
        selected_category = Category.where(parent_id: list_params)
        childs = selected_category.sort{|a, b| a.code <=> b.code}
        data = []
        childs.each do |child|
          data << {id: child.id, name: child.name}
        end
        respond_to do |format|
          format.json { render json: data }
        end
      end
    
      def list_params
        params.require(:category_id)
      end
    
    
    
    
    
    
    #カテゴリセット
      def category_select
    root = Category.find(1)
    @categories = root.sub_categories.includes(:sub_categories).sort{|a, b| a.code <=> b.code}
    @sub_categories = @categories[0].sub_categories.sort{|a, b| a.code <=> b.code}
      end
    
[/code]

### Model

[code]

    class Category < ActiveRecord::Base
      has_many :items
      has_many   :sub_categories, class_name: 'Category', foreign_key: 'parent_id'
      belongs_to :categories, class_name: 'Category', foreign_key: 'parent_id'
    end
    
[/code]

.

[code]

    #親カテゴリ
    Category.create(:name => 'root', :code => 000000, :parent_id => 0)
    Category.create(:name => 'メンズ', :code => 100000, :parent_id => 1)#2
    Category.create(:name => 'レディース', :code => 200000, :parent_id => 1)#3
    Category.create(:name => 'キッズ', :code => 300000, :parent_id => 1)#4
    Category.create(:name => 'インテリア', :code => 400000, :parent_id => 1)#5
    Category.create(:name => '家電製品', :code => 500000, :parent_id => 1)#6
    Category.create(:name => '本', :code => 600000, :parent_id => 1)#7
    Category.create(:name => 'チケット', :code => 700000, :parent_id => 1)#8
    Category.create(:name => 'おもちゃ', :code => 800000, :parent_id => 1)#9
    Category.create(:name => 'エンターテインメント', :code => 900000, :parent_id => 1)#10
    Category.create(:name => 'スポーツ', :code => 1000000, :parent_id => 1)#11
    
    
    #メンズ子カテゴリ
    Category.create(:name => 'トップス', :code => 100100, :parent_id => 2)
    Category.create(:name => 'アウター', :code => 100200, :parent_id => 2)
    Category.create(:name => 'パンツ', :code => 100300, :parent_id => 2)
    Category.create(:name => '靴', :code => 100400, :parent_id => 2)
    Category.create(:name => '帽子', :code => 100500, :parent_id => 2)
    Category.create(:name => 'その他', :code => 100600, :parent_id => 2)
    
    #レディース子カテゴリ
    Category.create(:name => 'トップス', :code => 200100, :parent_id => 3)
    Category.create(:name => 'アウター', :code => 200200, :parent_id => 3)
    Category.create(:name => 'パンツ', :code => 200300, :parent_id => 3)
    Category.create(:name => '靴', :code => 200400, :parent_id => 3)
    Category.create(:name => '帽子', :code => 200500, :parent_id => 3)
    Category.create(:name => 'その他', :code => 200600, :parent_id => 3)
    
    
    
    #キッズ子カテゴリ
    Category.create(:name => 'トップス', :code => 300100, :parent_id => 4)
    Category.create(:name => 'アウター', :code => 300200, :parent_id => 4)
    Category.create(:name => 'パンツ', :code => 300300, :parent_id => 4)
    Category.create(:name => '靴', :code => 300400, :parent_id => 4)
    Category.create(:name => '帽子', :code => 300500, :parent_id => 4)
    Category.create(:name => 'その他', :code => 300600, :parent_id => 4)
    
    
    #インテリア/家具の子カテゴリー
    Category.create(:name => 'ソファ/椅子', :code => 400100, :parent_id => 5)
    Category.create(:name => 'テーブル/机', :code => 400200, :parent_id => 5)
    Category.create(:name => 'ベット/寝具', :code => 400300, :parent_id => 5)
    Category.create(:name => '収納', :code => 400400, :parent_id => 5)
    Category.create(:name => '照明', :code => 400500, :parent_id => 5)
    Category.create(:name => 'キッチン', :code => 400600, :parent_id => 5)
    Category.create(:name => 'その他', :code => 400700, :parent_id => 5)
    
    
    
    #家電製品の子カテゴリー
    Category.create(:name => 'パソコン/タブレット', :code => 500100, :parent_id => 6)
    Category.create(:name => 'スマートフォン/携帯', :code => 500200, :parent_id => 6)
    Category.create(:name => '生活家電', :code => 500300, :parent_id => 6)
    Category.create(:name => 'オーディオ機器', :code => 500400, :parent_id => 6)
    Category.create(:name => 'テレビ/映像機器', :code => 500500, :parent_id => 6)
    Category.create(:name => 'カメラ', :code => 500600, :parent_id => 6)
    Category.create(:name => 'その他', :code => 500700, :parent_id => 6)
    
    
    #本の子カテゴリー
    Category.create(:name => '漫画/コミック', :code => 600100, :parent_id => 7)
    Category.create(:name => '文学/小説', :code => 600200, :parent_id => 7)
    Category.create(:name => 'アート/エンターテインメント', :code => 600300, :parent_id => 7)
    Category.create(:name => 'ノンフィクション', :code => 600400, :parent_id => 7)
    Category.create(:name => '雑誌', :code => 600500, :parent_id => 7)
    Category.create(:name => '人文/社会', :code => 600600, :parent_id => 7)
    Category.create(:name => '趣味/スポーツ', :code => 600700, :parent_id => 7)
    Category.create(:name => '住まい/暮らし', :code => 600800, :parent_id => 7)
    Category.create(:name => 'ビジネス/経済', :code => 600900, :parent_id => 7)
    Category.create(:name => 'コンピュータ/インターネット', :code => 401000, :parent_id => 7)
    Category.create(:name => '教育', :code => 601100, :parent_id => 7)
    Category.create(:name => '医学', :code => 601200, :parent_id => 7)
    Category.create(:name => 'その他', :code => 601300, :parent_id => 7)
    
    
    
    #チケットの子カテゴリー
    Category.create(:name => '国内アーティスト', :code => 700100, :parent_id => 8)
    Category.create(:name => '海外アーティスト', :code => 700200, :parent_id => 8)
    Category.create(:name => 'イベント系', :code => 700300, :parent_id => 8)
    Category.create(:name => 'スポーツ', :code => 700400, :parent_id => 8)
    Category.create(:name => '演劇/舞台', :code => 700500, :parent_id => 8)
    Category.create(:name => 'ミュージカル/お笑い', :code => 700600, :parent_id => 8)
    Category.create(:name => 'その他', :code => 700700, :parent_id => 8)
    
    
    #おもちゃの子カテゴリー
    Category.create(:name => 'テレビゲーム', :code => 800100, :parent_id => 9)
    Category.create(:name => 'トレーディングカード', :code => 800200, :parent_id => 9)
    Category.create(:name => 'フィギア', :code => 800300, :parent_id => 9)
    Category.create(:name => 'プラモデル', :code => 800400, :parent_id => 9)
    Category.create(:name => 'ラジコン', :code => 800500, :parent_id => 9)
    Category.create(:name => 'ぬいぐるみ', :code => 800600, :parent_id => 9)
    Category.create(:name => 'LEGO', :code => 800700, :parent_id => 9)
    Category.create(:name => 'その他', :code => 800800, :parent_id => 9)
    
    
    
    
    #エンターテインメントの子カテゴリー
    Category.create(:name => 'DVD/Blu-ray', :code => 900100, :parent_id => 10)
    Category.create(:name => '楽器', :code => 900200, :parent_id => 10)
    Category.create(:name => '美術品', :code => 900300, :parent_id => 10)
    Category.create(:name => 'コレクション', :code => 900400, :parent_id => 10)
    Category.create(:name => 'その他', :code => 900500, :parent_id => 10)
    
    
    #スポーツの子カテゴリー
    Category.create(:name => 'スポーツ用品', :code => 1000100, :parent_id => 11)
    Category.create(:name => 'アウトドア用品', :code => 1000200, :parent_id => 11)
    Category.create(:name => '自電車', :code => 1000300, :parent_id => 11)
    Category.create(:name => 'フィッシング', :code => 1000400, :parent_id => 11)
    Category.create(:name => 'その他', :code => 1000500, :parent_id => 11)
    
[/code]

### 2015.04.10 追記

1日かけてもまだ解決していません。  
画面の状態は以下のようになっています。

![画像の説明をここに入力](https://i.stack.imgur.com/shqV8.png)

> 画面表示直後のカテゴリ、サブカテゴリ周りのHTML

![画面表示直後](https://i.stack.imgur.com/W1yPL.png)

> カテゴリを変更し、選択できないテキストが表示されている状態のHTML

![カテゴリを変更し、選択できないテキストが表示されている状態のHTML](https://i.stack.imgur.com/RA2e5.png)

> javascript
[code]

    0: option
    1: option
    2: option
    3: option
    4: option
    5: option
    6: option
    7: option
    accessKey: ""
    attributes: NamedNodeMap
    autofocus: false
    baseURI: "http://0.0.0.0:3000/items/new/"
    childElementCount: 8
    childNodes: NodeList[8]
    children: HTMLCollection[8]
    classList: DOMTokenList[5]
    className: "form-control select select-default sub-category-select select2-offscreen"
    clientHeight: 15
    clientLeft: 0
    clientTop: 0
    clientWidth: 220
    contentEditable: "inherit"
    dataset: DOMStringMap
    dir: ""
    disabled: false
    draggable: false
    firstChild: option
    firstElementChild: option
    form: form#new_item.new_item
    hidden: false
    id: "item_sub_category_id"
    innerHTML: "<option></option><option value="30">ソファ/椅子</option><option value="31">テーブル/机</option><option value="32">ベット/寝具</option><option value="33">収納</option><option value="34">照明</option><option value="35">キッチン</option><option value="36">その他</option>"
    innerText: ""
    isContentEditable: false
    jQuery11020925654900027439: 2725
    labels: NodeList[0]
    lang: ""
    lastChild: option
    lastElementChild: option
    length: 8
    localName: "select"
    multiple: false
    name: "item[sub_category_id]"
    namespaceURI: "http://www.w3.org/1999/xhtml"
    nextElementSibling: null
    nextSibling: text
    nodeName: "SELECT"
    nodeType: 1
    nodeValue: null
    offsetHeight: 15
    offsetLeft: 0
    offsetParent: div.col-sm-9.col-md-3.col-lg-3
    offsetTop: 0
    offsetWidth: 220
    onabort: null
    onautocomplete: null
    onautocompleteerror: null
    onbeforecopy: null
    onbeforecut: null
    onbeforepaste: null
    onblur: null
    oncancel: null
    oncanplay: null
    oncanplaythrough: null
    onchange: null
    onclick: null
    onclose: null
    oncontextmenu: null
    oncopy: null
    oncuechange: null
    oncut: null
    ondblclick: null
    ondrag: null
    ondragend: null
    ondragenter: null
    ondragleave: null
    ondragover: null
    ondragstart: null
    ondrop: null
    ondurationchange: null
    onemptied: null
    onended: null
    onerror: null
    onfocus: null
    oninput: null
    oninvalid: null
    onkeydown: null
    onkeypress: null
    onkeyup: null
    onload: null
    onloadeddata: null
    onloadedmetadata: null
    onloadstart: null
    onmousedown: null
    onmouseenter: null
    onmouseleave: null
    onmousemove: null
    onmouseout: null
    onmouseover: null
    onmouseup: null
    onmousewheel: null
    onpaste: null
    onpause: null
    onplay: null
    onplaying: null
    onprogress: null
    onratechange: null
    onreset: null
    onresize: null
    onscroll: null
    onsearch: null
    onseeked: null
    onseeking: null
    onselect: null
    onselectstart: null
    onshow: null
    onstalled: null
    onsubmit: null
    onsuspend: null
    ontimeupdate: null
    ontoggle: null
    onvolumechange: null
    onwaiting: null
    onwebkitfullscreenchange: null
    onwebkitfullscreenerror: null
    onwheel: null
    options: HTMLOptionsCollection[8]
    outerHTML: "<select class="form-control select select-default sub-category-select select2-offscreen" id="item_sub_category_id" name="item[sub_category_id]" tabindex="-1" title=""><option></option><option value="30">ソファ/椅子</option><option value="31">テーブル/机</option><option value="32">ベット/寝具</option><option value="33">収納</option><option value="34">照明</option><option value="35">キッチン</option><option value="36">その他</option></select>"
    outerText: ""
    ownerDocument: document
    parentElement: div.col-sm-9.col-md-3.col-lg-3
    parentNode: div.col-sm-9.col-md-3.col-lg-3
    prefix: null
    previousElementSibling: div#s2id_item_sub_category_id.select2-container.form-control.select.select-default.sub-category-select
    previousSibling: div#s2id_item_sub_category_id.select2-container.form-control.select.select-default.sub-category-select
    readOnly: false
    required: false
    scrollHeight: 15
    scrollLeft: 0
    scrollTop: 0
    scrollWidth: 220
    selectedIndex: 0
    selectedOptions: HTMLCollection[1]
    shadowRoot: null
    size: 0
    spellcheck: true
    style: CSSStyleDeclaration
    tabIndex: -1
    tagName: "SELECT"
    textContent: "ソファ/椅子テーブル/机ベット/寝具収納照明キッチンその他"
    title: ""
    translate: true
    type: "select-one"
    validationMessage: ""
    validity: ValidityState
    value: ""
    webkitdropzone: ""
    willValidate: true
[/code]

> 画面表示直後のカテゴリ、サブカテゴリ周りのHTML子カテゴリ

![子カテゴリ](https://i.stack.imgur.com/8TtDB.png)

> javascript

![画像の説明をここに入力](https://i.stack.imgur.com/15Uuc.png)


CC BY-SA 3.0
2015-04-04T09:04:08.927
8761
2015-04-11T00:28:08.750
2015-04-10T11:38:18.327
9161
9161
question
ruby-on-rails
Rails4.1 validateで弾かれるとセレクトボックスの値が未選択状態に戻る


「validateエラーで差し戻された場合」とあるので、おそらくフォームをサブミット（更新ボタン等をクリック）したときの話だと推測します。  
なのでここではAjaxの話は直接関係しなさそうです。

「選択したカテゴリが未選択状態に戻ってしまう」のは親カテゴリ、子カテゴリ、どちらの話でしょうか？

とりあえず、`category.id.to_s`の`to_s`はいらない気がしますね。  
最初はこれが原因かなと思いましたが、手持ちのRailsプロジェクトで試したところ特に変化はありませんでした。

あと、「子カテゴリが未選択になる」と仮定すると、`sub_categories`の中身が親カテゴリに関連するカテゴリになっていないから、という理由が推測されます。

いずれにせよ、正確な原因を推測するのにはまだ情報が不足しているので、下記のような情報を追記してください。

  * Viewの全体像（最低限 `categories`や`sub_categories`を定義している部分）
  * Controllerのコード
  * 以下のようなSubmit時のログ

.

[code]

    Started POST "/fruits" for 127.0.0.1 at 2015-04-06 04:07:13 +0900
    Processing by FruitsController#create as HTML
      Parameters: {"utf8"=>"✓", "authenticity_token"=>"igF7cN7KTp2JgokY1v1v6qGrb0mfC51hS1G9F4KxMtk=", "fruit"=>{"name"=>"Strawberry"}, "commit"=>"Save"}
    
[/code]

## EDIT

> , :selected =>
> f.object.category_id)を追加したところ親カテゴリはvalidate後も値を保持するようになりました。sub_categoryは,
> :selected => f.object.sub_category_id)を追加しても未選択状態に戻ってしまいます。 <%= f.select
> :category_id, options_for_select(categories.collect { |category|
> [category.name, category.id.to_s] }, :selected => f.object.category_id),
> {:include_blank => '選択してください' }, { id: 'category_select', class: 'form-
> control select select-default' } %>

`selected`を追加すれば保持するようになった、っていうのがちょっと謎ですね・・・。  
とはいえ、こちらではそれ以上追跡のしようがないのでとりあえず置いておきましょう。

一方、子カテゴリの方ですが、submit後、セレクトボックスを開いたときに選択されるべき項目は含まれていますか？  
たとえば、submit前に「野菜 > にんじん」と選択したのであれば、submit後も子カテゴリのセレクトボックスに「にんじん」が入って必要があります。

もし入っていないのであれば、`options_for_select(sub_categories.collect
...`の`sub_categories`の中身が正しく設定されていないことになります。

一方、入っているのであれば`sub_categories`が持っている`id`と`f.object.sub_category_id`の中身が何らかの理由でマッチしていないんだと思います。

`<% Rails.logger.debug sub_categories.inspect %>`や`<% Rails.logger.debug
f.object.sub_category_id %>`のようなデバッグコードを仕込んで、viewが受け取っているオブジェクトの中身を検証してみてください。

## EDIT 2

> sub_categoriesはnilでした。 .to_sがないと動かなくなったりするのもおかしいのですし もうバグだらけでhogehogeって感じです。

新しく情報を追加してもらいましたが、`category_select`がどこでどのように呼ばれているのか、といった情報もないと意図した通りのデータが得られない理由も推測しにくいです。

いずれにせよ、スタックオーバーフロー上で情報のキャッチボールをしていても原因と解決策が見つかるまでにはかなり時間がかかりそうです。  
こういったデバッグは実際にコードの全体像やアプリの動きを見ながら進めるのが一番良いので、一緒にデバッグしてくれる友人や同僚に付き合ってもらうのが一番の近道かなと思います。

そういった技術者が見つからない場合はお近くのRuby勉強会に飛び込んで「教えてください！」と頼んでみるのはいかがでしょうか？

## EDIT 3

若干仕様は異なりますが、ほぼ同じ事が実現できるサンプルアプリを作ってみました。

![Image](https://f.st-
hatena.com/images/fotolife/J/JunichiIto/20150408/20150408071950.gif)

ソースコードはこちらにあります。

<https://github.com/JunichiIto/category-select-sandbox>

まずこれをローカルで動かしてみて、自分のコードと比較してみるとデバッグも少し効率よく進むかもしれません。  
参考にしてみてください。

## EDIT 4

> サブカテゴリは表示されるのですが selectできないテキストで表示されます

おそらくselect boxじゃないオブジェクトに対してoptionをappendしてしまってるんだと思います。

<https://github.com/JunichiIto/category-select-
sandbox/blob/master/app/assets/javascripts/items.coffee#L14>

↑このセレクタで正しくselect boxを選択できているか確認してください。

ちなみにクライアントサイド（ブラウザ側）のデバッグはChrome デベロッパーツールのようなツールを使いこなさないとかなり大変です。  
逆に言うと、こうしたツールが使いこなせれば、なぜうまく動かないのか自分で解決できるようになります。  
もしこういったツールをうまく使えていないのであれば、まずツールの使い方を学習するのが先決かもしれません。

## EDIT 5

質問で挙げられている設計とは若干異なりますが、こちらに解説記事を書きました。  
良かったらこちらも参考にしてみてください。

[Ajaxでセレクトボックスの中身が動的に変わるRailsアプリの作り方](http://qiita.com/jnchito/items/59a5f6bea3d7be84b839)

## EDIT 6

Chromeデベロッパーツールを使って以下の情報を追記してください。

  1. 画面表示直後のカテゴリ、サブカテゴリ周りのHTML
  2. カテゴリを変更し、選択できないテキストが表示されている状態のHTML
  3. サブカテゴリを置き換えているJavaScript

HTMLは下図のようにセレクトボックスを右クリックして「要素の検証」を選ぶと表示されます。（「ソースの表示」ではありません）

![画像の説明をここに入力](https://i.stack.imgur.com/LDpQG.png)

もしくは可能であればプロジェクト全体のソースコードをGitHub等に公開してもらった方が解決が早いかもしれません。

## EDIT 7

追記ありがとうございます。  
[Select2](https://select2.github.io/)を使ってるようですね。  
おそらくSelect2が動的に要素を変更するので、EDIT 3で示したようなシンプルなサンプルアプリと状況が変わっているんだと思います。  
一度Select2を外して素のHTMLで動作させてみてください。

それから追記してもらった「画面表示直後のカテゴリ、サブカテゴリ周りのHTML」ですが、親カテゴリのHTMLしか見えていません。  
サブカテゴリのHTMLも表示してください。（たぶんセレクトボックスが見えていなくてもdivタグぐらいは出ているはず）

あとJavaScriptはapplication.jsのようなソースコード（changeイベントを処理している部分）を見せてください。

## EDIT 8

Select2を外す = Select2を使わない、という意味です。  
おそらくどこかのJavaScriptで `$('select').select2();` みたいなコードを書いたんじゃないでしょうか？  
そこをコメントアウトすればSelect2は動作しないはずです。

あと、追記してほしかったJavaScriptは一番最初に書いてあった `$(document).on('change', ...` みたいなコードです。  
全く手を加えていないなら追記しなくても良いですが、試行錯誤の過程で手を加えてあるならもう一度JSのコード全体を見せてください。

P.S.  
ちなみにkitaさんは独学でプログラミングをされているのでしょうか？（僕にはそのように見えます）  
やはりオンラインのやりとりだけではなかなか先に進まないので、kitaさんには席を並べて一緒にプログラミングやデバッグをしてくれる仲間や師匠が必要な気がします。

## EDIT 9

Flat UIを組みこんで動かしてみました。  
こんな感じでイメージは合っていますか？

![画像の説明をここに入力](https://i.stack.imgur.com/sBNax.gif)

ソースコードはこちらにあります。

<https://github.com/JunichiIto/category-select-sandbox/tree/select-2>

EDIT 3のコードとのdiffはこちらです。

<https://github.com/JunichiIto/category-select-sandbox/pull/1/files>

### ポイント1：JSで操作するセレクトボックスはclassでなく、idで指定する

以下はViewのコード（diff）です。

[code]

       <div class="field">
         <%= f.label :category_id %><br>
    -    <%= f.select :category_id, category_collection(Category.find_by_name('root')), {include_blank: true}, {class: 'category-select'} %>
    +    <%= f.select :category_id, category_collection(Category.find_by_name('root')), {include_blank: true}, {id: 'category-select', class: 'form-control select select-primary select-block mbl'} %>
       </div>
       <% style = "display:none;" if @item.category.try(:sub_categories).blank? %>
       <div class="field field-sub-category" style="<%= style %>">
         <%= f.label :sub_category_id %><br>
    -    <%= f.select :sub_category_id, category_collection(@item.category), {include_blank: true}, {class: 'sub-category-select'} %>
    +    <%= f.select :sub_category_id, category_collection(@item.category), {include_blank: true}, {id: 'sub-category-select', class: 'form-control select select-primary select-block mbl'} %>
       </div>
       <div class="actions">
    -    <%= f.submit 'Save' %>
    +    <%= f.submit 'Save', class: 'btn btn-info' %>
       </div>
    
[/code]

classにすると、Select2が同じクラス名をコピーしてしまい、JSの処理時にHTMLがおかしくなります。

### ポイント2：オプションを入れ替えたら`select2`メソッドをもう一度呼び出す

以下は`items.coffee`のコードです。

[code]

             $.ajax
               url: url
               dataType: "json"
               success: (results) ->
                 $('.field-sub-category').toggle(results.length > 0)
    -            $select.empty()
    +            resetSelect($select)
                 appendOptions($select, results)
    +            $select.select2
    +              dropdownCssClass: 'dropdown-inverse'
    
[/code]

`appendOptions`でオプションを入れ替えた後に、`$select.select2`をもう一回呼び出しています。

### ポイント3：オプションを入れ替える前にSelect2の内容も一緒にクリアする

以下は`items.coffee`のコードです。

[code]

    +    resetSelect = ($select) ->
    +      $select.empty()
    +      $select.select2('val', '')
    
[/code]

`$select.select2('val', '')`でSelect2の中身をクリアしています。  
オプションを入れ替える前にこれを呼び出さないと、オプションがどんどん追記されてしまいます。

参考までに、JavaScriptに変更した後のコードも載せておきます。

[code]

    (function() {
      $(function() {
        $("select").select2({
          dropdownCssClass: 'dropdown-inverse'
        });
        return (function() {
          var appendOptions, replaceSubCategoryOptions, resetSelect;
          appendOptions = function($select, results) {
            var option;
            option = $('<option>');
            $select.append(option);
            return $.each(results, function() {
              option = $('<option>');
              option.val(this.id);
              option.text(this.name);
              return $select.append(option);
            });
          };
          resetSelect = function($select) {
            $select.empty();
            return $select.select2('val', '');
          };
          replaceSubCategoryOptions = function() {
            var $select, url;
            url = $(this).find('option:selected').data().subCategoriesPath;
            $select = $(this).closest('form').find('#sub-category-select');
            if (url != null) {
              return $.ajax({
                url: url,
                dataType: "json",
                success: function(results) {
                  $('.field-sub-category').toggle(results.length > 0);
                  resetSelect($select);
                  appendOptions($select, results);
                  return $select.select2({
                    dropdownCssClass: 'dropdown-inverse'
                  });
                }
              });
            } else {
              $('.field-sub-category').hide();
              return resetSelect($select);
            }
          };
          return $('#category-select').change(replaceSubCategoryOptions);
        })();
      });
    
    }).call(this);
    
[/code]

以上のようなコードを参考にするとうまくいくのではないでしょうか？  
試してみてください。


CC BY-SA 3.0
2015-04-05T19:10:26.230
8800
2015-04-11T00:28:08.750
2017-03-10T09:42:48.880
-1
85
8761
answer