Kaminari pagination control with fixed page link count
Asked Answered
M

3

10

I would like to have Kaminari to show pagination links at fixed count with pagination control, for example 10 links on each navigation page. Kaminari default shows 6 page links at first page and the page links continue to grow when you continue browsing until you reach 9 items.

I show in picture here, when I first load it will have 5 links in total.

enter image description here

When I continue to browse, it will grow.

enter image description here

Until you browse for the 5th link, it only show total links of 9.

enter image description here

How do I consistently have a link count of 10 even at the beginning or the end of the navigation with Kaminari. I have try with Kaminari config.window, but that's not what I want.

Markmarkdown answered 15/11, 2012 at 10:27 Comment(1)
Kaminari's default options are stupid. most people want to gray out the prev and next buttons. most people want a constant item count like you do. Worse, the updated version now uses an internal link_to_unless method that makes it even harder to implement a greyed out prev/next linksIerna
F
10

You could monkey patch Kaminari's Paginator and PageProxy classes. By overriding methods like relevant_pages, inside_window?, left_outer?, and right_outer? you can control when a page link gets shown in the paginate view helper.

To get started, create a new file in config/initializers called kaminari.rb and paste in the following code:

module Kaminari
  module Helpers
    class Paginator < Tag
      def relevant_pages(options)
        1..options[:total_pages]
      end

      class PageProxy
        def inside_window?
          if @options[:current_page] <= @options[:window]
            @page <= (@options[:window] * 2) + 1
          elsif (@options[:total_pages] - @options[:current_page].number) < @options[:window]
            @page >= (@options[:total_pages] - (@options[:window] * 2))
          else
            (@options[:current_page] - @page).abs <= @options[:window]
          end
        end
      end
    end
  end
end

It's not pretty but it gets the job done. If you set window: 5 in your view then this will always show a total of 10 links plus another <span> for the current page.

To learn more, check out the source code https://github.com/amatsuda/kaminari/blob/master/lib/kaminari/helpers/paginator.rb

Frivolity answered 5/4, 2013 at 21:25 Comment(1)
Thanks @Keith. We are using your solution. We just show 3 numeric links by setting window option to 1 with your patch. This works perfectly on most mobiles but last few pagination links get stacked in iPhone 5Bloke
J
2

I wasn't able to get the answer above to work. What I did was to calculate the window size and pass it into my pagination partial.

controller

  window = @items.current_page < 5 ? 5 - @items.current_page : 1
  render partial: 'pagination; locals: {items: @items, window: window}

_pagination.html.slim

.col-lg-6.pull-right
  ...
  = paginate items, remote: true, window: window
  ...
Jilt answered 9/6, 2015 at 17:38 Comment(0)
I
1

For who are using customized theme:

In view (slim file):

...other code...
- each_side = 4 # in case want to show 10 pages
= paginate items, left: each_side * 2 + 1, right: each_side * 2 + 1, theme: 'your-theme'

In app/views/kaminari/your-theme/_paginator.html.slim:

ruby:
  each_side = 4 # in case want to show 10 pages
  if current_page - each_side < 1
    top_page = 1
    bottom_page = top_page + each_side * 2 + 1 > total_pages ? total_pages : top_page + each_side * 2 + 1
  elsif current_page + each_side + 1 > total_pages
    bottom_page = total_pages
    top_page = bottom_page - each_side * 2 - 1 < 1 ? 1 : bottom_page - each_side * 2 - 1
  else
    top_page = current_page - each_side
    bottom_page = current_page + each_side + 1
  end

= paginator.render do
  nav.pagination
    ul.pagination-list
      # for rendering first_page link
      # == first_page_tag unless current_page.first?
      == prev_page_tag unless current_page.first?
      - each_page do |page|
        - if page <= bottom_page && page >= top_page
          == page_tag page
      == next_page_tag unless current_page.last?
      # for rendering last_page link
      # == last_page_tag unless current_page.last?
Icy answered 6/12, 2018 at 4:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.