Customize Kaminari Pagination
Kaminari is a popular pagination gem for Rails application and provides a decent default template to get started.
In this tutorial, we will customize Kaminari template and allow to change dynamically the limit per page. We will use the following mock-up:
Mockup layout
To get started, follow the steps below:
git clone -b get_started https://github.com/Maroo-b/kaminari_customization_tutorial.git
bundle install
rails db:setup
So we start by editing the app/views/kaminari/_paginator.html.erb partial:
<%= paginator.render do -%>
<nav class="pagination">
<%= first_page_tag unless current_page.first? %>
<%= prev_page_tag unless current_page.first? %>
<%= "#{current_page} of #{total_pages}" %>
<% unless current_page.out_of_range? %>
<%= next_page_tag unless current_page.last? %>
<%= last_page_tag unless current_page.last? %>
<% end %>
</nav>
<% end -%>
Next, to display Bootstrap glyphicons for navigation we edit the locale file config/locales/en.yml
en:
views:
pagination:
first: 'First'
previous: '<span class="glyphicon glyphicon-menu-left" aria-hidden="true"></span>'
next: '<span class="glyphicon glyphicon-menu-right" aria-hidden="true"></span>'
last: 'Last'
Now it’s time to add dynamic page limits, I suggest to add the page sizes inside Kaminari config file like to avoid hardcoding values in the view.
config/initializers/kaminari_config.rb file
# frozen_string_literal: true
Kaminari.configure do |config|
config.default_per_page = 10
# config.max_per_page = nil
# config.window = 4
# config.outer_window = 0
# config.left = 0
# config.right = 0
# config.page_method_name = :page
# config.param_name = :page
# config.params_on_first_page = false
end
PAGE_SIZES = [25, 50, 75]
And to display the pagination alongside filter links
app/views/articles/index.html.erb
<h3 class="text-center">Articles</h3>
<div class="clearfix">
<div class="pull-left">
<%= paginate items %>
</div>
<div class="pagination-filter pull-right">
<span>Items per page</span>
<ul>
<% PAGE_SIZES.each do |size| %>
<li><%= link_to size, url_for(per_page: size) %></li>
<% end %>
</ul>
</div>
</div>
<%= render partial: 'item_table', locals: {items: @articles} %>
Next step is to edit the articles_controller file
def index
if params[:per_page].present?
@articles = Article.all.page(params[:page]).per(params[:per_page])
else
@articles = Article.all.page(params[:page])
end
end
and to wrap it up we add a simple CSS:
.pagination-filter{
margin: 20px 0;
ul {
display: inline-block;
margin-left: -25px;
}
li {
display: inline-block;
list-style-type: none;
}
li a:after {
content: ' |';
}
li:last-child a:after {
content: '';
}
}
The code implementation is available on the following Github repo.
Have fun and keep coding 🙂