Ajax pagination with Kaminari

Giới thiệu

Kaminari là một gem rất phổ biến để phân trang khi làm việc với Rails. Trong bài viết này, chúng ta cùng nhau tìm hiểu cách phân trang sử dụng ajax để giúp cho quá trình này diễn ra mượt mà hơn ✌️ .

Chuẩn bị

Tạo app, thêm gem kaminari

Tạo 1 sample app tạm đặt tên là ajax_pagination và add thêm gem kaminari vào Gemfile:

rails new ajax_pagination

TrongGemfile:

gem 'kaminari'

Sau đó chạy bundle install.

Tạo User

Bước tiếp theo, cần tạo model User với 2 trường nameage. Để cho nhanh, ta dùng scaffold:

rails g scaffold user name:string age:integer
rails db:migrate

Seeds

Trong db/seeds.rb:

puts "create users"
60.times do |n|
  User.create! name: "user_#{n}", age: n
end

Implement pagination:

users_controller.rb:

@users = User.page(params[:page]).per(10)

index.html.erb

<%= paginate @users %>

Add jquery

Gemfile:

gem 'jquery-rails`

Process

Thêm id cho pagination index.html.erb:

<div id="paginator">
  <%= paginate @users %>
</div>

Render partial user:

  • Tạo file: _user.html.erb:
<tr>
  <td><%= user.name %></td>
  <td><%= user.age %></td>
  <td><%= link_to 'Show', user %></td>
  <td><%= link_to 'Edit', edit_user_path(user) %></td>
  <td><%= link_to 'Destroy', user, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
  • Ở trang index, render partial ra như sau:
<tbody id="users">
  <%= render @users %>
</tbody>

OK và đây là phần chính, để dùng được ajax links, ta chỉ cần add thêm 1 param như sau:

<%= paginate @users, remote: true %>

Yeah, trông đơn giản nhưng mà chưa đủ ✌️ Cần tạo thêm file: app/views/users/index.js.erb

$("#users").html("<%= j render(@users) %>");
$("#paginator").html("<%= j paginate(@users, remote: true) %>");

Với #users là id của users list.

Vậy là xong 😛

Code trang index:

<p id="notice"><%= notice %></p>

<h1>Users</h1>

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Age</th>
      <th colspan="3"></th>
    </tr>
  </thead>

  <tbody id="users">
    <%= render @users %>
  </tbody>
</table>

<br>

<%= link_to 'New User', new_user_path %>

<div id="paginator">
  <%= paginate @users, remote: true %>
</div>

Wrapup

Trông có vẻ dài dòng vậy, thức chất việc làm ajax cho pagination chỉ tổng kết gói gọn trong 3 dòng code

# Thêm remote true ở pagination
<%= paginate @users, remote: true %>

# Và:
$("#users").html("<%= j render(@users) %>");
$("#paginator").html("<%= j paginate(@users, remote: true) %>");

Các bạn có thể làm thêm phần ajax cho action destroy user, giữ lại trang hiện tại mà ko phải load về trang đầu (thêm 1 biến đếm ở controller mỗi khi xóa).

Repo tham khảo thêm ở đây.

Thanks for reading.