Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

Rails: HotwireCombobox gemが素晴らしすぎるという話(翻訳)

概要

原著者の許諾を得て翻訳・公開いたします。

josefarias/hotwire_combobox - GitHub

Rails: HotwireCombobox gemが素晴らしすぎるという話(翻訳)

hotwireと相性バツグンの「コンボボックス(Web向けのドロップダウンボックスやセレクトボックスの一種で、項目を手入力すると他のオプションをフィルタできる)」の書き方を知るという大きな幸運を引き当てたので、今週の記事の執筆予定を変更することにしました。その後でたまたま目にしたRuby Weeklyで、同じことを既にやっている人がいることを知りました。

ちなみにその人は作者のJose Fariasで、これをHotwireComboboxと呼んでいます。ドキュメントページにはさまざまなデモが掲載されているので、皆さんもぜひお試しください!

このHotwireCombobox gemの最も素晴らしい点は(これはRails 7のJavaScriptがimport mapsに移行したことで私にとって最も嬉しい点でもあります)、フロントエンドのアセットと仲良く共存できることです。つまり、今後バージョンが上がってもバックエンドとフロントエンドの同期が取れなくなるリスクがありません。

実際、HotwireCombobox gemのセットアップは最小限で済むので、 私のアプリで使われていたf.collection_selectボックスをf.comboboxに置き換えたときの全変更内容を本記事で公開することにします。

🔗 インストール方法

Gemfileに以下を追加してからbundleコマンドを実行します。

gem "hotwire_combobox"

アプリでstylesheet_link_tagが書かれている場所(おそらくレイアウトの<head>タグにあります)を探して、その上の行にcombobox_style_tagをコピペします。私の場合は以下のようになりました。

<%= combobox_style_tag %>
<%= stylesheet_link_tag "tailwind", "inter-font", "data-turbo-track": "reload" %>
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>

🔗 to_combobox_displayをモデルに追加する

私はActive Recordのモデルにビューがらみの不要なものを追加するのは嫌いなのですが、この機能をなるべく手軽に使えるようにしたかったので、自分のEquipmentモデルに以下を追加して、コンボボックスのリストにtitle属性を表示するようにしました。

class Equipment < ApplicationRecord
  #...
  def to_combobox_display
    title
  end
end

🔗 select入力を差し替える

続いて、以下のcollection_selectをすべて置き換えました。

<%= f.collection_select :equipment_id, Equipment.all.order(:title), :id, :title, include_blank: true %>

上をf.comboboxで以下のように書き換えます。

<%= f.combobox :equipment_id, Equipment.all.order(:title), include_blank: true %>

原注

2024/03/29時点では、include_blank: trueだけでは動かなかった(#125)ため、自分のカスタムTailwindFormBuilderでパッチを当てました。

訳注: #125はその後すぐ#130で修正されました。

🔗 コンボボックスの外観をカスタマイズする

このコンボボックスで最も手こずったのは、他のカスタムフォーム入力と外観を同じにすることでした。私はTailwindを使っているので、@layer base {}の内部で必要なものを上書きするために、このHotwireCombobox gemが公開しているCSSクラスや変数を対象としました。

以下は、Tailwindを使っていない方には意味不明に見えるかもしれません。

/* hotwirecombobox */

.hw-combobox__main__wrapper {
  @apply mt-1 rounded-md shadow-sm max-w-screen-md;
}

.hw-combobox__main__wrapper input:focus {
  @apply ring-0;
}

.hw-combobox__dialog__input {
  @apply rounded-lg focus:ring-0 focus:border-accent ;
}

:root {
  --hw-focus-color: rgb(var(--accent));
  --hw-border-width--thick: 1px;
  --hw-combobox-width: 100%;
  --hw-combobox-width--multiple: 100%;
}

🔗 以上でおしまいです!

上に挙げた私のスニペットに「ないもの」にご注目ください。import mapのコンフィグもなければ、StimulusコントローラをJavaScriptで登録するステップもありません。すべてこのgemが独自に処理してくれます。

私の経験では、この種のUIを作るのはいつも大変だったので、このように簡単に追加できて、アプリの既存のフロントエンドともうまく連携できるコンポーネントが使えるのは、ひたすら素晴らしいことです。

Jose、ありがとう!💜

関連記事

Rails 7: importmap-rails gem README(翻訳)


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。