selectとoptionタグをjQueryを使って動的に追加する

## デモ(動画)
[![Image from Gyazo](https://i.gyazo.com/b10d4585fc1d6a48a8b33171687f0dd7.gif)](https://gyazo.com/b10d4585fc1d6a48a8b33171687f0dd7)

## やりたいこと
上記のGIF通り、
**カテゴリーが選択されたと同時に、親カテゴリーに紐づく子カテゴリーが出てくるようにしたい。**
入れ子構造については以下を参照
[【追記予定】awesome_nested_setを使った入れ子構造のDB設計](https://qiita.com/katsu105/items/e83508e7110ec2a69e9d)


##　実装概要
jQueryのajaxメソッドを使って、カテゴリーが選択されたら子カテゴリーがappendされるようにした。

##　コード

### routing
```ruby:route.rb
Rails.application.routes.draw do
  root 'products#new'
  resources :products,  only: [:create] do
<!-- 今回はsearchアクションをajaxメソッドで叩きます-->
    collection do
      get 'search'
    end
  end
end
```

### view

```haml:new.html.haml
= form_for @product do |f|
  = f.label :name
  = f.text_field :name, placeholder: "商品名を入力"
  
  #cat
    = f.select :category_id, Category.roots.map {|i| ["#{i.name}", i.id]}, { selected: @product.category_id, include_blank: true }, {id: "l_category"}
```

### js

```javascript:category.js
$(document).on('turbolinks:load', function() {

  // selectを追加するHTML
  var cat_seach = $("#cat");

  function appendSelect(catNum) {
    if(catNum == 1) {
      var select_id = `m_category`
    } else if(catNum == 2) {
      var select_id = `s_category`
    }
    var html =
    `<select name="product[category_id]" id="${select_id}">
        <option value>---</option>
    </select>`
    cat_seach.append(html)
  }


  // optionを追加するHTML
  function appendCat(catOption, catNum) {
    if (catNum == 1) {
      var appendId = $("#m_category")
    } else if (catNum == 2) {
      var appendId = $("#s_category")
    }
    appendId.append(
      $("<option>")
        .val($(catOption).attr('id'))
        .text($(catOption).attr('name'))
    )
  }

  // Lカテゴリーが選択された時のアクション
  $("#l_category").on('change', function() {
    l_cat = $(this).val()
    $("#m_category, #s_category").remove()

    // ajaxでリクエストを送信
      $.ajax({
        type: "GET",
        url: "/products/search",
        data: {l_cat: l_cat},
        dataType: 'json'
      })
      // doneメソッドでappendする
      .done(function(m_cat) {
        var catNum = 1
        appendSelect(catNum)
        m_cat.forEach(function(m_cat) {
          appendCat(m_cat, catNum)
        })
      })
    })

// Mカテゴリーが選択された時のアクション
  $(document).on('change', "#m_category", function() {
    m_cat = $(this).val()
    $("#s_category").remove()

    $.ajax({
      type: "GET",
      url: "/products/search",
      data: {m_cat: m_cat},
      dataType: 'json'
    })
    .done(function(s_cat) {
      var catNum = 2
      appendSelect(catNum)
      s_cat.forEach(function(s_cat) {
        appendCat(s_cat, catNum)
      })
    })
  })
})

```

### controller

```ruby:categories_controller.rb
<!--関係ないアクションは省略しています-->
  def search
    if params[:l_cat]
      @m_cat = Category.find(params[:l_cat]).children
    else
      @s_cat = Category.find(params[:m_cat]).children
    end
    respond_to do |format|
      format.html
      format.json
    end
  end
```

### jbuilder

```ruby:search.json.jbuilder
json.array! @m_cat do |m_cat|
  json.id   m_cat.id
  json.name m_cat.name
end

json.array! @s_cat do |s_cat|
  json.id   s_cat.id
  json.name s_cat.name
end
```


## 勉強になったところ

### optionタグの追加の方法

```javascript:optionの追加

$("#m_category").append(
      $("<option>")
        .val($(m_cat).attr('id'))
        .text($(m_cat).attr('name'))
    )
  }
```
こういう風に書くことで、selectタグのoptionが追加できることを知りました。
始めはselectを追加すればいいじゃん！と思ってましたが、配列形式で渡ってくるため、配列の中身分selectが増えてしまい、上手な方法が浮かばなかったので、こちらの方法にしました。

参考記事
・jQuery でセレクトボックスのプルダウン項目（option 要素）を追加／削除する方法
https://webllica.com/jquery-select-option-add-del/