Skip to content

studioraketa/phoenix_pagination

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

30 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Pagination

A small library providing a simple pagination based on limit and offset and a very naive and limited implementation of a cursor based pagination.

Installation

Add phoenix_pagination to your list of dependencies in mix.exs:

def deps do
  [
    {:phoenix_pagination, "~> 0.8.0", git: "https://github.com/studioraketa/phoenix_pagination.git"}
  ]
end

Usage

With your DB queries

Use the Paginatin.Ecto module inside your Repo.

defmodule MyApp.Repo do
  use Ecto.Repo,
    otp_app: :my_app,
    adapter: Ecto.Adapters.Postgres

  use Pagination.Ecto, page_size: 20, cursor_page_size: 5
end

A queryable can be paginated with limit/offset pagination like so:

  Repo.paginate(Post, :offset, %{"page" => 5})

or

  Repo.paginate(Post, :offset, %{page: 5})

The result is a struct:

  iex(6)> list = Repo.paginate(Post, :offset, %{page: 5})
  ...
  iex(7)> list.current_page
  5
  iex(8)> list.pages_count
  18
  iex(9)> list.entries_count
  350
  iex(10)> list.page_size
  20
  iex(11)> list.entries
  [.....]

A queryable can be paginated with a cursor based pagination like so:

Warning Currently the library works correctly only with unique fields!

  Repo.paginate(Post, :cursor, %{"cursor" => 5, "field" => :id, "direction" => :desc})

or

  Repo.paginate(Post, :cursor, %{cursor: 5, field: :id, direction: :desc})

The result is a struct:

  iex(6)> list = Repo.paginate(Post, :cursor)
  ...
  iex(10)> list.page_size
  5
  iex(11)> list.entries
  [%Post{id: 1}, ..., %Post{id: 5}]
  iex(11)> list.cursor
  "NQ=="

In the html templates

Inside your MyAppWeb in the view import the Pagination.Html module.

import Pagination.Html

and then in the eex templates you can do the following:

  <%= paginate_list(
    @list,
    fn page ->
      Routes.post_path(@conn, :index, [page: page])
    end
  ) %>

which will generate the links for you:

<nav class="pagination">
  <a href="/posts?page=6">Previous</a>
  <a href="/posts?page=1">1</a>
  <a href="/posts?page=2">2</a>
  <em>...</em>
  <a href="/posts?page=4">4</a>
  <a href="/posts?page=5">5</a>
  <a href="/posts?page=6">6</a>
  <em class="current-page">7</em>
  <a href="/posts?page=8">8</a>
  <a href="/posts?page=9">9</a>
  <a href="/posts?page=10">10</a>
  <em>...</em>
  <a href="/posts?page=17">17</a>
  <a href="/posts?page=18">18</a>
  <a href="/posts?page=8">Next</a>
</nav>

It is possible to overrdie the Next, Previous and ... labels like so:

  <%= paginate_list(
    @list,
    fn page ->
      Routes.post_path(@conn, :index, [page: page])
    end,
    [
      next_label: "->",
      previous_label: "<-",
      etc_label: "----"
    ]
  ) %>

You can choose to render links to all pages. Use the option show_all_pages:

  <%= paginate_list(
    @list,
    fn page ->
      Routes.post_path(@conn, :index, [page: page])
    end,
    [
      show_all_pages: true,
    ]
  ) %>

Development

  • Do some changes
  • Run MIX_ENV=test mix ecto.create to create the test Databas
  • Run MIX_ENV=test mix ecto.migrate to migrate it
  • Run bin/test to check if everything works

TODO

  • Limit/Offset pagination
    • Work with queries including group by clauses.
    • Improve documentation and tests
      • Move the query relevant tests to a separate file query_test.exs
  • Cursor pagination
    • Work with queries including group by clauses.
    • Work with queries including order by clauses.
    • Improve documentation and tests
      • Move the query relevant tests to a separate file query_test.exs

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published