概要
インクリメンタルでドロップダウンの選択肢を絞り込めるselect2-railsのgemはとても便利なんだけど、jQueryに依存しているので、Rails 7 + StimulusなどのjQueryを使わないモダンな環境では使用をためらってしまうかと思います。
Select2の代わりに使えるTom SelectがSelect2同様に簡単で便利だったので紹介します。
環境
- Rails 7.0.3
- stimulus-rails
- jsbundling-rails(importmap-railsでもいけるはず)
- Bootstrap 5(なくてもいけます)
コマンド
1. yarnでライブラリをTom Selectを追加する
これでTom SelectのJavaScriptがコンパイルされるようになります。
yarn add tom-select
2. Tom SelectのCSSをインポートする
これをやらないとスタイルが適用されず、崩れたドロップダウンが2つ表示される感じになります。公式ドキュメントでは見つけにくくて、はまりました。
プロジェクトでBootstrapを使っている場合は、以下のようになります。
@import "tom-select/dist/css/tom-select.bootstrap5";
Bootstrapを使っていない場合は、以下のようになります。
@import 'tom-select/dist/css/tom-select';
3. JavaScriptをインポートする
まず、Stimulusのコントローラーを作成します。
bin/rails g stimulus SelectController
作成されたファイルで、TomSelectをimportして使います。
import { Controller } from "@hotwired/stimulus"
import TomSelect from "tom-select"
// Connects to data-controller="select"
export default class extends Controller {
connect() {
// 初期化処理を書く
const config = {};
new TomSelect(this.element, config);
}
}
以下の記述はimportmap-railsでは不要です。jsbundling-railsでは自動で追加されます。
import { application } from "./application"
...
import SelectController from "./select_controller"
application.register("select", SelectController)
4. viewsにselectを追加する
Shopモデルにareaというプロパティーがあるとすると、こんな感じになります。
<%= bootstrap_form_with(model: @shop, url: shops_path) do |form| %>
<div class="col-6">
<%= form.select :area, Area.all.pluck(:name, :id), { include_blank: 'エリアを選択' }, data: { controller: "select" } %>
</div>
<% end %>
Bootstrapなしのform_withでもいけるし、selectの代わりにcollection_selectでもいけます。
<%= form_with(model: @shop, url: shops_path) do |form| %>
<div class="col-6">
<%= form.collection_select :area_id, Area.all, :id, :name, { include_blank: 'エリアを選択' }, data: { controller: "select" } %>
</div>
<% end %>
できたもの
この例では、ドロップダウンの選択肢を静的に取得していますが、動的に取得する方法もあります。公式のサンプルを見てみてください!
参考