お世話になります。これは以前質問したシステムの続きになります。あれから、試行錯誤の末に検索部分はAjaxを実装することができたのですが、kaminariを使ったページャーの挙動がおかしいままになっており、その原因がわからずに難航しています。
参考にしたページがこちらです
Kaminariをjsonでajax化する
#環境
- Apache2.4.38
- Ruby2.5.1
- Rails5.2.3
- Sqlite3
なお、自分はRailsに不慣れなので、erb、javascriptで記述しています。
#プログラム
##コントローラ
cities_controller
ruby
1class CitiesController < ApplicationController 2 protect_from_forgery :except => [:index,:get_area,:paginate] 3 before_action :get_area, only: [:show, :edit, :update, :destroy] 4 5 # GET /cities 6 # GET /cities.json 7 PER = 20 8 9 def index 10 unless params[:q].blank? 11 @q = City.ransack(params[:q]) 12 @q.sorts = 'population desc' if @q.sorts.empty? 13 @cities = @q.result.page(params[:page]).per(10) 14 #コンテナのレンダリング 15 p_cities = render_to_string( 16 partial: 'ajax_container', 17 locals: { :cities => @cities} 18 ) 19 #ページャーのレンダリング 20 p_pager = render_to_string( 21 partial: 'ajax_pager', 22 locals: { :cities => @cities }, 23 remote: true 24 ) 25 if request.xhr? 26 render json:{ 27 container: p_cities, 28 pager: p_pager 29 } 30 end 31 else 32 @q = City.ransack(params[:q]) 33 @q.sorts = 'population desc' if @q.sorts.empty? 34 @cities = @q.result.page(params[:page]).per(10) 35 end 36 end 37 38#後略
##ルーティング
rb
1Rails.application.routes.draw do 2 resources :cities 3 get 'cities/index', to: 'cities#index' 4 post 'cities/index' ,to: 'cities#index' 5 # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html 6end
##テンプレート
index.html.erb
erb
1<%- model_class = City -%> 2<div class="page-header"> 3 <h1><%=t '.title', :default => model_class.model_name.human.pluralize.titleize %></h1> 4</div> 5 6<div class="panel panel-default" id="list"> 7 <div class="panel-heading"> 8 <div class="panel-title">検索</div> 9 </div> 10 <div class="panel-body"> 11 <%= search_form_for(@q , :id=>'city-form', :remote => true) do |f| %> 12 <div class="row"> 13 <!-- 都道府県名の完全一致検索 --> 14 <div class="col-sm-6"> 15 <div class="form-group"> 16 <%= f.label :pref_no_eq %> 17 <%= f.select :pref_no_eq,Pref::PREF.to_a,{},{class:'form-control'} %> 18 </div> 19 </div> 20 21 <!-- 市名の部分一致検索 --> 22 <div class="col-sm-4"> 23 <div class="form-group"> 24 <%= f.label :city_name_cont %> 25 <%= f.text_field :city_name_cont, class: "form-control", placeholder: "部分一致" %> 26 </div> 27 </div> 28 </div><!-- @row --> 29 30 <div class="row"> 31 <!-- 人口の範囲検索 --> 32 <div class="form-group"> 33 <div class="col-sm-12 form-inline"> 34 <%= f.label :'人口の範囲検索' %> 35 <%= f.search_field :population_gteq, class: "form-control", placeholder: "最低値" %> 36 ~ 37 <%= f.search_field :population_lteq, class: "form-control", placeholder: "最高値" %> 38 <%= f.submit '検索', class: "btn btn-primary btn-search", id: "sbm" %> 39 <%= link_to 'クリア', url_for, class: "btn btn-default" %> 40 <%= link_to t('.new', :default => t("helpers.links.new")),new_city_path,:class => 'btn btn-primary' %> 41 </div> 42 43 </div> 44 </div><!-- @row --> 45 <% end %> 46 <div> 47</div> 48 49 <table class="table table-striped" id="tbl"> 50 <thead> 51 <tr> 52 <th><%= model_class.human_attribute_name(:id) %></th> 53 <th><%= model_class.human_attribute_name(:base_no) %></th> 54 <th><%= model_class.human_attribute_name(:city_name) %></th> 55 <th><%= model_class.human_attribute_name(:pref_no) %></th> 56 <th><%= model_class.human_attribute_name(:population) %></th> 57 <th><%=t '.actions', :default => t("helpers.actions") %></th> 58 </tr> 59 </thead> 60 <tbody id="ajax-response-wrapper"> 61 <%= render 'ajax_container' %> 62 </tbody> 63 </table> 64 <div id="pager"><%= render 'ajax_pager' %></div> 65 66<script type="text/javascript"> 67 $(function(){ 68 $(".form-control").each(function(){ 69 $(this).on('change focusout',function(){ 70 $('#sbm').click(); 71 }) 72 }) 73 $("#city-form").on("ajax:success",function(e){ 74 data = e.detail[0] 75 $('#ajax-response-wrapper').empty().append(data.container) 76 $('#pager').empty().append(data.pager) 77 }) 78 $("#city-form").on("ajax:fail",function(event,data,status,xhr){ 79 alert("fail!") 80 }) 81 }) 82</script>
##パーシャル
_ajax_container.html.erb
erb
1<% @cities.each do |city| %> 2 <tr id="t"> 3 <td><%= link_to city.id, city_path(city) %></td> 4 <td><%= city.base_no %></td> 5 <td><%= city.city_name %></td> 6 <td><%= city.pref_no %></td> 7 <td><%= city.population %></td> 8 <td> 9 <%= link_to t('.show', :default => t("helpers.links.show")), 10 city_path(city), :class => 'btn btn-default btn-xs' %> 11 <%= link_to t('.edit', :default => t("helpers.links.edit")), 12 edit_city_path(city), :class => 'btn btn-default btn-xs' %> 13 <%= link_to t('.destroy', :default => t("helpers.links.destroy")), 14 city_path(city), 15 :method => :delete, 16 :data => { :confirm => t('.confirm', :default => t("helpers.links.confirm", :default => 'Are you sure?')) }, 17 :class => 'btn btn-xs btn-danger' %> 18 </td> 19 </tr> 20<% end %> 21
_ajax_pager.html.erb
erb
1<%= paginate @cities, window: 2 %>
現行の画面
- 検索機能はRansack、ページャー機能はkaminariを使用(前と変わらず)
- プルダウンの値変更、またはテキストボックスのフォーカスアウトによって、検索結果をAjaxで返す。Ajaxの手法として、テンプレートをパーシャル化して、レスポンスに対し、一度消去したタグを再度付与する。
- 検索結果を10件ずつ表示している
- 検索結果が10件以上となる場合は、ページャーが付与される
- 検索結果が10件以下となる場合は、ページャーは付されない
発生している問題
- ページャーの遷移がおかしく、最初に読み込んだ状態から、10件以上検索される結果を表示し、その画面のページャーから2ページめを押しても、1ページ目の表示が残ります。その状態でもう一度2ページ目を押すと、次のページに遷移します。
ところが、キャッシュの関係なのかそのバグを再現できない場合もあります。また、ページャー無しの検索結果から再びページャーありの検索結果となった場合にページ遷移を行うと、同様のバグが起こったりします。
#やってみたこと
- ページャーにremote: trueを記述してみた → ページャー機能のAjax自体が機能しなくなりました
- テンプレートのパーシャル部分を削除した → ページャーの遷移後に表示されなくなってしまいました
ほかにもコントローラのメソッドを通常制御とAjaxで分けてみたり、パーシャルの記述を変えてみたり色々試行錯誤してみたのですが、解決しないので皆様の助力を仰がせていただきます。
よろしくお願いします。
回答1件
あなたの回答
tips
プレビュー