Back to Pagy

Keynav Js

docs/toolbox/paginators/keynav_js.md

43.5.34.7 KB
Original Source

:icon-key:  :keynav_js{{ include "snippets/js-required" }}


:keynav_js is a fast KEYSET paginator that supports the UI. It's a pagy exclusive technique.

The Keynav pagination adds the numeric variables (@page, @last, @previous, @next, @in) to its instances, supporting their usage with the UI. It does so by transparently exchanging data with the client, that stores the state of the pagination.

If something goes wrong on the client side, it falls back to the :countless paginator seamlessly.

{{ include "snippets/run-app" app: "keynav" anchor: "keysets" }}

!!!warning This documentation extends the :keyset documentation. It's easier to understand if you familiarize with the :keyset docs. !!!

==- :icon-list-ordered:  Setup

Keyset Setup

JavaScript Support

=== :icon-tools:  Usage

ruby
@pagy, @records = pagy(:keynav_js, collection, **options)
  • @pagy is the pagination instance. It provides the readers and the helpers to use in your code.
  • @records is the eager-loaded Array of the page records.

==- :icon-sliders:  Options

{{ include "options/keyset" }}

==- :icon-mention:  Readers

last : The last page.

pages : The number of pages.

previous : The previous page

{{ include "snippets/keyset-readers" }}

==- :icon-log:  In-depth: Cutoffs Filtering

Let's take a new look at the diagram of the keyset pagination explained in the Keyset documentation:

                  │ first page (10)  >│ second page (10) >│ last page (9)  >│
beginning of set >[· · · · · · · · · X]· · · · · · · · · Y]· · · · · · · · ·]< end of set
                                      ▲                   ▲
                                   cutoff-X            cutoff-Y

Let's suppose that we navigate till page #3 (i.e., the last page), and we click on the link for page #2. We have stored the cutoff-X, so we can pull the 10 records after cutoff-X again as we did the first time... but are we sure that we would get the same results?

Let's suppose that the database just changed: 1 record was inserted before cutoff-X, and 2 records were deleted after cutoff-X...

                  │ page #1 (11)       >│ page #2 (8)  >│ page #3 (9)    >│
beginning of set >[· · · · · · · · · · X]· · · · · · · Y]· · · · · · · · ·]< end of set
                                        ▲               ▲
                                   cutoff-X        cutoff-Y

At this point pulling 10 records from the cutoff-X would get also the first 2 records from page 3, if you navigate on page 3, you will pull the same 2 records again also for page #3.

Indeed, not only the results have changed, but the cutoffs appear to have also shifted their absolute position in the set. In reality, the cutoffs have the same value as before, so they maintained their relative position in the set. However, now there is a different number of records falling into the same pages, which is totally consistent with the changes, but possibly unexpected. That is... if you have the mindset of OFFSET pagination, where the pages are split by number of records (absolute position) and not by their position relative to the records in the set.

!!! The main goal of pagination is to split the results into manageable chunks and ensure it is as fast and accurate as possible, so the variation in the page size seems not relevant to that. However, should it be relevant to you, you can always use the classic OFFSET pagination and accept its slowness and inaccuracy. !!!

Pagy keynav doesn't use the LIMIT to pull the records of already visited pages. Instead, it replaces the LIMIT with the same filter used for the beginning of the page, but it just compounds it with the negated filter of the ending of the page.

For example, the filtering of the page could be logically described like:

- Page #1 `WHERE NOT AFTER CUTOFF-X`                    <- only ending filter
- Page #2 `WHERE AFTER CUTOFF-X AND NOT AFTER CUTOFF-Y` <- combined beginning + ending filter
- Page #3 `WHERE AFTER CUTOFF-Y LIMIT 10`               <- regular beginning filter (no cutoff for last page)

!!! Implementing page-rebalancing When the number of records on a visited page has drastically changed, it would be helpful to mitigate the surprise effect on the user by:

  • Automatically compacting the empty (or almost empty) visited pages.
  • Automatically splitting the excessively grown visited pages. !!!

==- :icon-alert:  Caveat

!!!warning Nav bar links beyond the highest visited page are not known/displayed. !!!

===