Я пытаюсь реализовать нумерацию страниц в своем проекте Rails, используя драгоценный камень Pagy. У меня есть модель Record
и индексное представление для отображения моего Records
в элементе и форма над таблицей для фильтрации таблицы, которая находится в частичном виде, содержащем в турбо-кадре.
Моя проблема заключается в том, что Pagy изначально разбивает результаты поиска на страницы (определенные как «records#search») внутри турбо-фрейма, но затем, когда я перехожу с одной страницы на другую, он сразу же переходит на эту страницу, как если бы я просматривал нефильтрованные результаты ( Запись.все).
Итак, конкретный сценарий заключается в том, что я нахожусь на маршруте «/records/», но хочу отфильтровать записи, где name == 'foo'
. Как только я отфильтрую таблицу, она покажет мне результаты в таблице, где name == 'foo'
на странице 1. Затем, если я нажму, чтобы перейти на страницу 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')
И это тоже не приводит ни к каким изменениям.
# 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
Ссылки на пагинацию должны находиться внутри турбофрейма, поскольку вы хотите, чтобы они обновлялись при навигации.
target: "_top"
– потому что вы хотите, чтобы другие ссылки перемещались за пределами фрейма, а ссылки на страницы находились внутри фрейма.autoscroll: true
— прокручивает вверх результатов поиска.turbo_action: "advance"
— обновляет текущий URL.
# 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"'
Почти всегда поиск должен представлять собой форму GET
:
# 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>
Большое спасибо! Кажется, это сработало для меня! Буду обновлять, если что-нибудь еще! Очень благодарен за время, которое вы потратили на написание такого подробного объяснения.