0
Help us understand the problem. What are the problem?

posted at

updated at

RailsアプリにChoices.jsを使ったセレクトボックスを作る

概要

Choices.jsを使ってセレクトボックスを作成しました

はじめに

現在、フィヨルドブートキャンプでチーム開発をしています。
Choices.jsというライブラリを使って、セレクトボックスを作成しましたが、情報が少なかったのでQiitaに記事として残しておきます。
初学者向けの内容となっています。

Choices.jsについて

軽量な選択ボックス/テキスト入力プラグインです。リッチなセレクトボックスが作れます→DEMO
Select2およびSelectizeに似ていますが、jQueryの依存関係はありません。
2年ほどリリースが止まっていたようですが、2021年の12月より再びメンテナンスされているようです。

インストール

  • npm
npm install choices.js
  • yarn
yarn add choices.js
  • stylesheet
    導入したらしっかりstylesheetで読み込みましょう。
    自分はこれを忘れて無駄な時間を過ごしてしまいました😅(忘れるのは初学者の自分だけだと思います)
    CDNは以下、その他ディレクトリで読み込むものなど多数あります(README参照)
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/choices.js@9.0.1/public/assets/styles/choices.min.css"/>

用語

専門用語というほどではないんですが、ここを読み解かないとうまく使いこなせませんでした。
ほとんどREADMEを翻訳したものだけど載せておきます。
(今回はセレクトボックスを作るので、テキストボックスとしての使い方は割愛)

用語 説明
Choice ユーザーが実際に選択できる値で、<option>要素と同等
Group 選択肢の集まりでその名の通りグループ。<optgroup>要素と同等
Item 選択された要素の<option value = "item">要素と同等

HTMLでのセレクトボックスはというと

<select name="spice">
 <option value="">スパイスを選択</option>
 <option value="garammasala">ガラムマサラ</option>
 <option value="coriander">コリアンダー</option>
 <option value="cumin">クミン</option>
</select>

となっているのでChoiceは<option>のこと、Itemは<option>valueだとわかります。

ということでChoices.jsを使って、もっとも簡単だと思われるコードを書いてみました

index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title>Spice select</title>
    <link
      rel="stylesheet"
      href="https://cdn.jsdelivr.net/npm/choices.js@9.0.1/public/assets/styles/choices.min.css"
      />
    <script src="https://cdn.jsdelivr.net/npm/choices.js@9.0.1/public/assets/scripts/choices.min.js"></script>
  </head>
  <body>
    <select name="spice" id="hoge">
      <option value="">スパイスを選択</option>
      <option value="garammasala">ガラムマサラ</option>
      <option value="coriander">コリアンダー</option>
      <option value="cumin">クミン</option>
    </select>
    <script>
      document.addEventListener("DOMContentLoaded", () => {
        new Choices("#hoge")
      })
    </script>
  </body>
</html>

Choices.js demo.gif
セレクトボックスにhogeというidを振って、Choicesオブジェクトを作る際に紐づけるだけです。
これでインクリメンタルサーチが簡単に使えるし、上の通りvalue属性でもヒットします。
選択肢が多くなったときに便利ですね。

開発者ツールを見てみるとclass="choices"data-type="select-one"などのタグが使われています。
<select>select-one<select multiple>select-multipleとなっていて、
オプションが反映できるか否かは、この入力タイプを確認するとわかりやすいと思います。

Railsでの使い方

再び簡単な復習になるんですが、既にSpiceモデルがあるとして、selectを使うと

select(:spice, :name, Spice.pluck(:name, :id), { include_blank: "スパイスを選択" })

collection_selectを使うと

collection_select(:spice, :name, Spice.all, :id, :name, prompt: "スパイスを選択")

これをHTMLで出力すると、いずれも

<select name="spice[name]" id="spice_name">
  <option value="">スパイスを選択</option>
  <option value="1">ガラムマサラ</option>
  <option value="2">コリアンダー</option>
  <option value="3">クミン</option>
</select>

のようになります。
こちらもこのセレクトボックスにidさえ付与すれば、Choices.jsが使用可能です。

ここからは実際に自分がチーム開発で実装したコードに、一部修正を加えたものを記載していきます。

環境とgem

  • ruby 3.1.0
  • Rails 6.1.4.4
  • webpacker 5.4.3
  • Choices.js
  • slim-rails

UserモデルとSpiceモデルが存在し、UserはSpice(好みのスパイス)を1つ持つような関係です。
CSSに関してはnode_modulesから読み込むように設定しています。

view

= f.label :spice, class: 'a-form-label'
= f.collection_select :spice_id, all_spices_with_empty, :id, :name, {}, { id: 'js-spice-select' }

フォーム内でのセレクトボックスです。
セレクトボックスにjs-spice-selectというidを付与しています。
all_spices_with_emptyは選択肢なしを含めた配列です。

def all_spices_with_empty
  Spice.all.to_a.unshift(Spice.new(name: '好みのスパイスなし'))
end

javascript

app/javascript/packs/application.js
import '../spice-select.js'

JavaScriptファイルをWebpacker経由で読み込んでいます。

app/javascript/spice-select.js
import Choices from 'choices.js'

document.addEventListener('DOMContentLoaded', () => {
  const element = document.getElementById('js-spice-select')
  if (element) {
    return new Choices(element, {
      removeItemButton: true,
      allowHTML: true,
      searchResultLimit: 10,
      searchPlaceholderValue: '検索ワード',
      noResultsText: '一致する情報は見つかりません',
      itemSelectText: '選択'
    })
  }
})

以上のように、少しだけオプションをつけてみます。
allowHTMLオプションをつけないと、以下のようなwarningが出ます。

Deprecation warning: allowHTML will default to false in a future release. 
To render HTML in Choices, you will need to set it to true. 
Setting allowHTML will suppress this message.

また、Choices.js関連の要素がなければ、下記のコンソールエラーが出てしまうのでif文を使っています。

Uncaught TypeError: Expected one of the following types text|select-one|select-multiple

と、ここまで作り終えたところで
Choice.js demo.gif
Choices.jsを使ったセレクトボックスが完成しました🎉

これがRailsでChoices.jsを使う初歩的な方法だと思います。
他にも選択肢を他からfetchして作成したり、複数の選択肢を選んだり、タグをつけたり、、、
などなどカスタマイズが可能なので、少しリッチなセレクトボックスを作成するのにいかがでしょうか?

最後に

最後までご覧いただきありがとうございました。本記事がどなたかのご参考になれば幸いです。
何かご意見やご感想などありましたら、お気軽にコメントや編集リクエストをお待ちしております🙏

参考文献

執筆にあたり、以下の記事を参考とさせていただきました。ありがとうございました🙇‍♂️

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
0
Help us understand the problem. What are the problem?