前回はsimple_formを使ったカスタムインプットの作成方法を紹介しました。今回はそのカスタム・インプットとbootstrapの『Typeahead』を組み合わせた便利なインプットを作成したいと思います。
Typeaheadとは
Typeaheadとは、Twitter Bootstrapが提供するJavascriptのひとつで、オートコンプリート付きのテキストフィールドを簡単に作成することができるjQueryプラグインです。
個人的には、BootstrapのJavascriptの中で、一番使える機能だと思っています。bootstrap-rails.gemを導入していれば、この便利な機能があなたのRailsアプリですぐに使用できます。さっそく使ってみましょう。
どこに適用するかというと・・・Bookを登録する際に『Author』という項目を入力しますね。
同一の著者が複数の本を執筆するのはよくあることです。そこで、データベースに登録されている全ての著者を入力候補としたオートコンプリート機能を実現してみることにします。
Typeaheadを適用する
ではさっそくソースを編集していきましょう。app/views/books/_form.html.erbを修正します。
📄_form.html.erb
<%= simple_form_for @book, :html => { :class => 'form-horizontal' } do |f| %> <%= f.input :title %> <%= f.input :author, input_html: { :"data-provide" => "typeahead", :"data-source" => '["test1", "test2"]', :autocomplete => "off" } %> <%= f.input :review, as: :review %> <%= f.input :description %> <div class="form-actions"> <%= f.button :submit, :class => 'btn-primary' %> <%= link_to t('.cancel', :default => t("helpers.links.cancel")), books_path, :class => 'btn' %> </div> <% end %>
authorインプットに input_htmlオプションを指定しました。『data-provide』に”typeahead”を指定すると自動的にtypeahead機能が付与されます。オートコンプリートの候補は『data-source』に配列形式で指定します。たったこれだけで素敵なオートコンプリート機能が使えるとは便利ですねえ。(autocompleteをoffにしているのは、ブラウザが勝手に提供する入力履歴オートコンプリートを表示しないようにするためです)
さっそく画面をリロードして動作を確認してみると・・・
ちゃんとできてる! まだ3行しか書いてなにのに、ここまで辿り着きました。あなおそろしやbootstrap・・・
では次に、オートコンプリートの入力候補をちゃんと実装しましょう。データベースから全ての『Author』を取得するようにします。
📄_form.html.erb
<%= f.input :author, input_html: { :"data-provide" => "typeahead", :"data-source" => Book.pluck(:author).compact.uniq.to_s, :autocomplete => "off" } %>
pluckメソッドを使い、ユニークなauthor一覧を取得しています。特に難しい箇所はないと思います。さて・・・ちゃんと動くのでしょうか??
うむ! ちゃんと動いてますよ!日本語が問題ないところも素敵です。
要件としてはこれで満たしているのですが、前回と同様にこのインプットをカスタム・インプットにして再利用性を高めましょう。他の画面でも著者を入力する場面がきっとあるはずです。
前回の ReviewInputと同様に、app/inputs/author_input.rbというファイルを作成して、カスタムインプットを定義します。
📄author_input.rb
class AuthorInput < SimpleForm::Inputs::StringInput def input input_html_options[:type] = "text" input_html_options[:"data-provide"] = "typeahead" input_html_options[:"data-source"] = Book.pluck(:author).compact.uniq.to_s input_html_options[:autocomplete] = "off" super end end
app/views/books/_form.html.erbも修正して、カスタムインプットを呼び出すようにします。
📄_form.html.erb
<%= simple_form_for @book, :html => { :class => 'form-horizontal' } do |f| %> <%= f.input :title %> <%= f.input :author, as: :author %> <%= f.input :review, as: :review %> <%= f.input :description %> <div class="form-actions"> <%= f.button :submit, :class => 'btn-primary' %> <%= link_to t('.cancel', :default => t("helpers.links.cancel")), books_path, :class => 'btn' %> </div> <% end %>
画面をリロードして動作を確認してみましょう。先程と同様に正しく動作するはずです。
入力候補を取得する
正しく動作はしていますが、イケてない箇所がありますね。それは、カスタムインプット内からBookモデルに直接アクセスして入力候補を取得していることです。View層からデータベースをいじり倒すのはよろしくありませんし、もし1画面に複数のAuthorインプットを配置する場合、無駄なデータベースアクセスが増えるのもよくありません。入力候補はコントローラで1回取得するようにしましょう。
app/controllers/books_controller.rbを修正しましょう。
📄books_controller.rb
class BooksController < ApplicationController before_action :set_input_sources, only: [:new, :edit, :create, :update] ... ... private ... ... def set_input_sources @author_input_source = Book.pluck(:author).compact.uniq.to_s end end
2行目でフィルタを登録しています。実際に著者候補を取得してくるのは8~10行目の set_input_sourcesメソッドです。アプリケーションの各所で著者インプットを使用するなら、このメソッドは ApplicationControllerに定義してもよいかもしれません。
続いて、author_input.rbを修正します。
📄author_input.rb
class AuthorInput < SimpleForm::Inputs::StringInput def input input_html_options[:type] = "text" input_html_options[:"data-provide"] = "typeahead" input_html_options[:"data-source"] = @builder.template.assigns["author_input_source"] input_html_options[:autocomplete] = "off" super end end
InputsクラスのコンテキストからViewのインスタンス変数にアクセスするには@builder.template.assigns["変数名"]
のように記述します。修正が完了したら、画面をリロードして最終確認です!
ディ・モールト(非常に良い)!! 軽快に動作するナイスなオートコンプリートの完成です!
今回で『simple_formとTwitter bootstrapで作る俺流鉄板Railsアプリ』は終了です。大した手間もなく、そこそこリッチなWebアプリケーションが作れることがお分かり頂けたでしょうか。simple_form/bootstrapには、この他にも便利な機能がいろいろとありますので、ぜひとも探訪してみてください。
関連する記事
- simple_formとTwitter bootstrapで作る俺流鉄板Railsアプリ(その2)
- simple_formとTwitter bootstrapで作る俺流鉄板Railsアプリ(その1)
- Ruby on Rails + Bootstrap3 + simple_form チュートリアル
- Rails + simple_form + Foundation 5 チュートリアル
- Railsアプリを『浅く』パフォーマンス・チューニングしてみる(その1)