refrakt/paginate
Pagination helpers for list views and JSON APIs.
Pages are numbered from 1 and fetched with LIMIT and OFFSET. That
works with any ORDER BY, lets visitors jump to any page and gives a
total count; for very large tables or infinite scrolling, paginate by
key (WHERE id < $last_id) instead.
Usage in a repo
pub fn list(db: pog.Connection, params: paginate.Params) -> paginate.Page(Post) {
let posts =
pog.query("SELECT ... ORDER BY id DESC LIMIT $1 OFFSET $2")
|> pog.parameter(pog.int(params.per_page))
|> pog.parameter(pog.int(paginate.offset(params)))
...
let total = // SELECT COUNT(*) FROM posts
paginate.page(posts, params, total)
}
Usage in a handler
const per_page = 20
pub fn index(req: Request, ctx: Context) -> Response {
let params = paginate.Params(page: paginate.page_number(req), per_page:)
post_repo.list(ctx.db, params)
|> post_views.index_view
|> root_layout.wrap("Posts")
|> wisp.html_response(200)
}
Usage in a view
case paginate.next_page(page) {
Ok(next) -> a([href(paginate.page_path("/posts", next))], [text("Next")])
Error(_) -> text("")
}
Types
A paginated result.
pub type Page(item) {
Page(
items: List(item),
page: Int,
per_page: Int,
total: Int,
total_pages: Int,
has_previous: Bool,
has_next: Bool,
)
}
Constructors
-
Page( items: List(item), page: Int, per_page: Int, total: Int, total_pages: Int, has_previous: Bool, has_next: Bool, )
Values
pub fn from_request(
req: request.Request(wisp.Connection),
) -> Params
Extract pagination params from the query string
(?page=2&per_page=10), with 20 items per page by default.
pub fn from_request_with(
req: request.Request(wisp.Connection),
per_page default: Int,
) -> Params
Extract pagination params from the query string (?page=2&per_page=10),
with per_page items per page when the query has no valid per_page.
A per_page from the query is kept between 1 and max_per_page.
pub const max_per_page: Int
The largest per_page that from_request and from_request_with
accept from a query string.
pub fn next_page(page: Page(item)) -> Result(Int, Nil)
The number of the page after this one, if there is one.
pub fn page(
items: List(item),
params: Params,
total: Int,
) -> Page(item)
Build a Page from items, params, and total count.
pub fn page_number(req: request.Request(wisp.Connection)) -> Int
The page number from the page query parameter. A missing, invalid,
zero or negative page number is page 1.
pub fn page_path(base_path: String, page_num: Int) -> String
The path of a page: page_path("/posts", 2) is "/posts?page=2".
pub fn page_url(
base_path: String,
page_num: Int,
per_page: Int,
) -> String
Generate a pagination query string for a given page number.
pub fn previous_page(page: Page(item)) -> Result(Int, Nil)
The number of the page before this one. Past the last page, it is the last page, so a visitor who followed a stale link can get back.