我正在尝试使用 Pagy gem 在我的 Rails 项目中实现分页。我有一个
Record
模型和索引视图,用于在元素中显示我的 Records
以及表格上方的表单,以过滤包含 Turbo Frame 的部分表格。
我的问题是,Pagy 最初确实在 Turbo 框架内对搜索结果(由“records#search”定义)进行分页,但是当我从一个页面单击到另一个页面时,它会立即转到该页面,就好像我正在浏览未过滤的结果一样(全部记录)。
因此,一个特定的场景是,如果我位于“/records/”路线上,但我想过滤其中
name == 'foo'
的记录。一旦我过滤了表格,它就会向我显示表格中第 1 页 name == 'foo'
处的结果。然后,如果我单击转到第 2 页以查看更多过滤结果,就好像我在未过滤的第 2 页,我将丢失结果,其中 name == 'foo'
。
所以在我的
RecordsController
中我有:
class RecordsController < ApplicationController
def index
@pagy, @records = pagy(Record.all, items: 25)
end
def search
records = Record.where('name LIKE ?', "%#{params[:name]}%")
records = records&.where('type LIKE ?', "%#{params[:type]}%") if params[:type].present?
render(partial: 'records_table', locals: { records: })
end
end
在我的
index.html.erb
中Records
:
<h1>Records</h1>
<%= render "record_search_form" %>
<%= render "records_table",
records: @records %>
<div class="pag-bar mt-5 pt-5">
<%== pagy_bootstrap_nav(@pagy) if @pagy.pages > 1 %>
</div>
record_search_form
部分内:
<div style="margin:0.75rem">
<%= form_with url: records_search_path, method: :post,
data: {
controller:"records-search",
records_search_target: "form",
turbo_frame:"records_table"} do |form| %>
<%= form.text_field :name %>
<%= form.text_field :type %>
<%= form.button "Search", class:"btn btn-primary" %>
<% end %>
</div>
里面
records_table
:
<%= turbo_frame_tag "records_table" do %>
<table>
<thead>
<tr>
<th>
ID
</th>
<th>
Name
</th>
<th>
Type
</th>
</tr>
</thead>
<tbody>
<% if records.present? %>
<% records.each do |record| %>
<tr>
<td><%= record.id %></td>
<td><%= record.name %></td>
<td><%= record.type %></td>
</tr>
<% end %>
<% end %>
</tbody>
</table>
<% end %>
我尝试更改我的
records#search
操作来渲染不同的 Pagy 实例:
def search
records = Record.where('name LIKE ?', "%#{params[:name]}%")
records = records&.where('type LIKE ?', "%#{params[:type]}%") if params[:type].present?
@pagy_results, @results = pagy(records, items: 25)
render(partial: 'records_table', locals: { records: @results })
end
然后将其包含在视图中,如下所示:
<h1>Records</h1>
<%= render "record_search_form" %>
<%= render "records_table",
records: @records %>
<div class="pag-bar mt-5 pt-5">
<%== pagy_bootstrap_nav(@pagy) if @pagy.pages > 1 %>
</div>
**<div class="pag-bar mt-5 pt-5">
<%== pagy_bootstrap_nav(@pagy_search) if @pagy_search.present? && @pagy_search.pages > 1 %>
</div>**
这会导致问题像以前一样发生(当我单击转到另一页结果时,就好像我已转到该页码,但未过滤结果)。
我也在里面尝试过这个
records#search
:
@pagy_search, @response = pagy(records, items: 100, pagy_url_for: 'records/search')
这样做也不会导致任何改变。
您应该首先使搜索工作正常,然后将其包装在 Turbo 框架中。几乎每次搜索都应该是
GET
形式。
# app/controllers/records_controller.rb
class RecordsController < ApplicationController
def index
scope = Record.all
scope = scope.where("name LIKE ?", "%#{params[:name]}%") if params[:name].present?
scope = scope.where("type LIKE ?", "%#{params[:type]}%") if params[:type].present?
@pagy, @records = pagy(scope, items: 25)
end
end
分页链接应该位于 Turbo 框架内,因为您希望它们在导航时更新。
target: "_top"
- 因为您希望其他链接在框架外部导航,而分页链接位于框架内。autoscroll: true
- 滚动到搜索结果的顶部。turbo_action: "advance"
- 更新当前网址。
# app/views/records/index.html.erb
<%= render "search_form" %>
<%= turbo_frame_tag "records_table", target: "_top", autoscroll: true,
data: {turbo_action: "advance"} do %>
<%= render "table", records: @records %>
<%== pagy_nav(@pagy) %>
<% end %>
默认情况下使分页链接在框架内导航:
# config/initializers/pagy.rb
Pagy::DEFAULT[:link_extra] = 'data-turbo-frame="_self"'
# app/views/records/_search_form.html.erb
<%= form_with url: records_path, method: :get,
data: {turbo_frame:"records_table"} do |form| %>
<%= form.text_field :name, value: params[:name] %>
<%= form.text_field :type, value: params[:type]%>
<%= form.button "Search", name: nil %>
<% end %>
<!-- app/views/records/_table.html.erb -->
<table>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<% records.each do |record| %>
<tr>
<td><%= record.id %></td>
<td><%= record.name %></td>
<td><%= record.type %></td>
</tr>
<% end %>
</tbody>
</table>