【備忘録】Rails7 Stimulus セレクトボックス 親子 複数 連動

会社を選択すると、現場と品目の選択肢に、アソシエーションされているレコードをセットする
![add_flow7.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/324819/67806d9c-4a2f-2c56-41b6-a9b76eb46162.gif)

```config/routes.rb
  resources :companies do
    get 'sites', on: :member
    get 'waste_kinds', on: :member
  end
```

```app/controllers/companies_controller.rb
  def sites
    company = Company.find(params[:id])
    sites = company.sites

    respond_to do |format|
      format.json { render json: sites }
    end
  end

  def waste_kinds
    company = Company.find(params[:id])
    waste_kinds = company.waste_kinds

    respond_to do |format|
      format.json { render json: waste_kinds }
    end
  end
  ```
  ```erb:app/views/industrial_wastes/_form.html.erb
  <div data-controller="company-select">
    <div class="my-5">
      <%= form.label :company_id, "会社" %><span class="text-red-500">*</span>
      <%= form.collection_select(
        :company_id,
        Company.all,
        :id,
        :name,
        {prompt: true},
        class: "company-select shadow appearance-none border border-gray-200 rounded w-full py-2 px-3 mt-2 text-gray-700 leading-tight focus:outline-none focus:shadow-outline",
        data: {
          action: "change->company-select#onChange"
        }
      ) %>
    </div>

    <div class="my-5">
      <%= form.label :site_id, "現場" %><span class="text-red-500">*</span>
      <%= form.collection_select(
        :site_id,
        [],
        :id,
        :name,
        {prompt: "会社を先に選択してください"},
        class: "shadow appearance-none border border-gray-200 rounded w-full py-2 px-3 mt-2 text-gray-700 leading-tight focus:outline-none focus:shadow-outline",
        data: {
          "company-select-target": "site"
        }
      ) %>
    </div>

    <div class="my-5">
      <%= form.label :waste_kind_id, "品目" %><span class="text-red-500">*</span>
      <%= form.collection_select(
        :waste_kind_id,
        [],
        :id,
        :name,
        {prompt: "会社を先に選択してください"},
        class: "shadow appearance-none border border-gray-200 rounded w-full py-2 px-3 mt-2 text-gray-700 leading-tight focus:outline-none focus:shadow-outline",
        data: {
          "company-select-target": "wasteKind"
        }
      ) %>
    </div>
  </div>
  ```
  ```app/javascript/controllers/company_select_controller.js
  import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  static targets = ["site", "wasteKind"]

  onChange(event) {
    this.updateSiteOptions(event.target.value);
    this.updateWasteKindOptions(event.target.value);
  }

  updateSiteOptions(companyId) {
    fetch(`/companies/${companyId}/sites.json`)
      .then(response => response.json())
      .then(data => {
        let options = data.map(site => `<option value="${site.id}">${site.name}</option>`);
        this.siteTarget.innerHTML = options.join("");
      });
  }

  updateWasteKindOptions(companyId) {
    fetch(`/companies/${companyId}/waste_kinds.json`)
      .then(response => response.json())
      .then(data => {
        let options = data.map(wasteKind => `<option value="${wasteKind.id}">${wasteKind.name}</option>`);
        this.wasteKindTarget.innerHTML = options.join("");
      });
  }
}
```