💬
stimulusでオートコンプリート機能実装
はじめに
エンジニア転職を目指しRuby on Railsを中心に学習中の初学者です。
備忘録として、躓いたことやケアレスミスも含め投稿します!誤っている箇所などありましたらご指摘いただけると幸いです
対象読者
- hotwire初学者
stimulusのセットアップ
1.stimulusのインストール
bin/rails stimulus:install
# docker利用の場合
docker compose run(コンテナ起動中は`exec`でも可) web bash
bin/rails stimulus:install
2. jsonファイルの確認
# 下記の記載があるか確認してください。
"@hotwired/stimulus": "^3.2.2"
3. app/javascript/controllersに実装したい機能のコントローラー追加
bin/rails generate stimulus example # `example`は適宜設定(例:オートコンプリート機能を実装したい場合は`autocomplete`等役割がわかる命名をする)
#補足
bin/rails g stimulus example
#どちらでも可能
rails g stimulus example
オートコンプリート機能
app/javascript/controllers/autocomplete_controller.js
// app/javascript/controllers/autocomplete_controller.js
import { Controller } from "@hotwired/stimulus"
// Connects to data-controller="autocomplete"
export default class extends Controller {
static values = { url: String }
static targets = ["results"]
search(event) {
const query = encodeURIComponent(event.target.value);
const url = `${this.urlValue}?q=${query}`;
fetch(url)
.then(response => response.json())
.then(data => {
this.updateResults(data);
})
.catch(error => console.error('Error fetching autocomplete data:', error));
}
updateResults(data) {
this.resultsTarget.innerHTML = '';
data.forEach(item => {
const li = document.createElement('li');
li.textContent = item.title;
li.addEventListener('click', () => {
this.selectResult(item);
});
this.resultsTarget.appendChild(li);
});
}
selectResult(item) {
this.element.querySelector('input').value = item.title;
this.resultsTarget.innerHTML = '';
}
}
検索フォーム
<!-- ransackなし -->
<%= form_with url: search_examples_path, method: :get, local: true do |form| %>
<div class="search-bar" data-controller="autocomplete" data-autocomplete-url-value="<%= autocomplete_examples(検索対象にしたいテーブル名)_path %>">
<%= form.label :query, "検索対象名" %>
<%= form.search_field :query %>
<%= form.submit "Search" %>
<ul data-autocomplete-target="results" class="autocomplete-results"></ul>
</div>
<% end %>
<!-- ransackあり -->
<%= search_form_for @q, url: url do |f| %>
<div class="search-bar" data-controller="autocomplete" data-autocomplete-url-value="<%= autocomplete_examples(検索対象にしたいテーブル名)_path %>">
<%= f.text_field :title_or_decription_cont, class: 'form-control', placeholder: t('.search_word'), data: { action: "input->autocomplete#search" } %>
<ul data-autocomplete-target="results" class="autocomplete-results"></ul>
</div>
<%= f.submit '検索', class: 'btn btn-primary' %>
<% end %>
コントローラーの編集
# ransackなし
def autocomplete
if params[:title].present?
@users = User.where('title LIKE ?', "%#{params[:title]}%")
else
@users = User.all
end
render json: @examples.as_json(only: [:id, :title, :decription])
end
# ransackあり
def autocomplete
@q = Facility.ransack(params[:q])
@examples = @q.result(distinct: true).limit(10)
render json: @examples.as_json(only: [:id, :title, :decription])
end
routes.rb
resources :examples, only: %i[index search(ransack未使用時) show new create update destroy] do
# 下記を設定↓
collection do
get :autocomplete
end
参考資料
Discussion