0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

stimulus-autocompleteを用いてオートコンプリート機能実装(Ruby on Rails)

Posted at

はじめに

エンジニア転職を目指しRuby on Railsを中心に学習中の初学者です。
ポートフォリオにオートコンプリート機能を実装したので、その備忘録として書き記しておきます。
誤っている箇所や改善点などありましたらご指摘いただけると幸いです。

開発環境

  • docker環境
  • ruby:3.3.6
  • ruby on rails: 7.2
  • tailwindcss: 4.0.15
  • hotwired/stimulus: 3.2.2
  • jsバンドラー(esbuild)を使用

前提

  • gem “ransack”を用いてすでに検索機能を実装している状態とします
  • Stimulusがすでにインストールされている状態とします

Rails7系ではrails new を実行した時にデフォルトで、
@hotwired/stimulus
gem "stimulus-rails”
がセットアップされています。

念の為実際に、インストールされているか確認します。

gemfile
gem "stimulus-rails"
package.json
{
    "@hotwired/stimulus": "^3.2.2",
    "@hotwired/turbo-rails": "^8.0.13",
    "@tailwindcss/cli": "^4.1.4",
    "tailwindcss": "^4.1.4"
  }

1.stimulus-autocompleteをインストールする

オートコンプリート機能を実装するために、まずstimulus-autocompleteをインストールします。stimulus-autocompleteの公式githubはこちら

jsバンドラーnode_modules(esbuild、rollup.js、Webpack など)を使用している場合は、npmからパッケージをインストールします。

以下を実行してインストール(docker環境)

$ docker compose exec web yarn add stimulus-autocomplete

上記を実行後、package.jsonに"stimulus-autocomplete" が追加されているのを確認します

package.json
{
    "@hotwired/stimulus": "^3.2.2",
    "@hotwired/turbo-rails": "^8.0.13",
    "@tailwindcss/cli": "^4.1.4",
    "stimulus-autocomplete": "^3.1.0", # 追加される
    "tailwindcss": "^4.1.4"
  }

2.Autocompleteコントローラを登録する

app/javascript/controllers/application.jsにAutocompleteコントローラーを登録します。

app/javascript/controllers/application.js
import { Application } from '@hotwired/stimulus'
import { Autocomplete } from 'stimulus-autocomplete' // 追加

const application = Application.start()
application.register('autocomplete', Autocomplete) // 追加

これによりdata-controller="autocomplete"の属性をHTMLに追加することで、インストールしたstimulus-autocompleteのAutocompleteコントローラが適用される。

3. 検索フォームを編集する

オートコンプリート機能を使用するには、検索フォームに以下の4つの追記が必要です。

<div data-controller="autocomplete" data-autocomplete-url-value="<%= autocomplete_〇〇_path %>" role="combobox">


<%= f.search_field :〇〇_cont, data: { autocomplete_target: 'input' } %>


<%= f.hidden_field :〇〇, data: { autocomplete_target: 'hidden' } %>


<ul class="list-group" data-autocomplete-target="results"></ul>

(1) data: { autocomplete_target: 'input' }を追記

まず検索フォームの<%= f.search_field %>の中に以下を追記します。

data: { autocomplete_target: 'input' }

autocomplete_targetというカスタムデータ属性を追加することでJavaScriptからこの要素を取得しオートコンプリートの機能を適用できます。

(2) divで囲む

そして<%= f.search_field %>を以下のdivタグで囲みます

<div data-controller="autocomplete" data-autocomplete-url-value="<%= autocomplete_〇〇_path %>" role="combobox">
</div>

そうすると以下のようになります。

<%= search_form_for q, url: url, class: "w-full" do |f| %>
  <div data-controller="autocomplete" data-autocomplete-url-value="<%= autocomplete_〇〇_path %>" role="combobox">
    <%= f.search_field :〇〇_cont data: { autocomplete_target: "input" } %>
  </div>
  <%= f.submit "検索" %>
<% end %>

data-autocomplete-url-value="<%= autocomplete_〇〇_path %>"ではRailsのビューテンプレートでURLを動的に生成してます。つまり〇〇controller の autocomplete アクションが実行され、オートコンプリートの機能が使われる時にそのアクションが呼び出されます。
のちにautocompleteアクションとルーティングを定義します。

(3) 隠しフィールドとulを追加する

<%= f.search_field %>の下に以下の2つのコードを追加する

<%= f.hidden_field :〇〇, data: { autocomplete_target: 'hidden' } %>

<ul class="list-group" data-autocomplete-target="results"></ul>

<%= f.hidden_field %>は「隠しフィールド」といい実際のページには表示されません。このフィールドは、ユーザーがオートコンプリートの候補から選んだ「値」を保持するために使われます。

<ul>には入力内容に応じたオートコンプリートの候補が挿入されます。

最終的にスタイルなどをあてると以下のようになりました。

<%= search_form_for q, url: url do |f| %>
  <div class="relative flex rounded-md w-full">
    <div data-controller="autocomplete" data-autocomplete-url-value="<%= autocomplete_books_path %>" role="combobox">
      <%= f.search_field :title_cont, class: 'flex-grow py-3 px-4 rounded-l-md border focus:outline-none w-[400px] h-[50px]', placeholder: "検索ワード", data: { autocomplete_target: 'input' } %>
      <%= f.hidden_field :title, data: { autocomplete_target: 'hidden' } %>
      <ul class="list-group absolute w-[400px]" data-autocomplete-target="results"></ul>
    </div>
    <%= f.submit "検索", class: 'btn bg-[#eed9b6] hover:bg-[#d4b886]' %>
  </div>
<% end %>

4. autocompleteアクションを定義する

routes.rbにautocompleteアクションのルーティングを追記します。

routes.rb
Rails.application.routes.draw do

  resources :books do
    # 以下を追加する
    collection do
      get :autocomplete
    end
  end
end

次にautocompleteアクションを定義します。

class booksController < ApplicationController

  # 以下を追加
  def autocomplete
    @books = Book.where("title like ?", "%#{params[:q]}%")
    respond_to do |format|
      format.js
    end
  end
end

これにより検索フォームに文字が入力されると、autocomplete_books_pathにリクエストが行われ、オートコンプリートの結果が取得されるようになります。

5.オートコンプリートの候補表示のviewを作成する

検索フォームの<ul>タグの中に挿入する用の<li>

<li class="list-group-item" role="option" data-autocomplete-value="〇〇">item</li>

を作成する必要がある。
なのでまずapp/views/〇〇/autocomplete.html.erb作成・編集する

app/views/books/autocomplete.html.erb
<% @books.each do |book| %>
  <li class="flex w-full items-center text-sm py-2 px-3 hover:bg-amber-100" role="option" data-autocomplete-value="<%= book.id %>" data-autocomplete-label="<%= book.title %>">
    <%= book.title %>
  </li>
<% end %>

6.完成

これで完成しました
5116625ca922ef2491cf08e167bf244b.gif

参考記事

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?