-
Notifications
You must be signed in to change notification settings - Fork 4
Paginate
This component is like the SSR version of Astro's SSG paginate()
function, create paginated dynamic routes using SSR
- Create array of pages from an array of data
- Use slot functions as render templates for pages
- Works with index pages
- Compatible with
<Pagination>
component for page link navigation - Alternatively render a page using the page number as a named slot
- Renders
error
slot if page number doesn't exist
This component is used when you want the to create a paginated dynamic route using SSR
---
import { Paginate } from 'astro-headless-ui';
const posts = await fetch('https://jsonplaceholder.typicode.com/posts').then(response => response.json())
---
<Paginate page={Astro.params.page} data={posts}>
{page => (
<section>
{ page.data.map(post => (
<article>
<h2>{post.title}</h2>
<p>{post.body}</p>
</article>
))}
</section>
)}
</Paginate>
Array of data to split into pages
Default: 10
Number of items assigned to a page
Default: 1
Page number of page to display/render
Example:
// src/pages/[...page].astro
<Paginate page={Astro.params.page}>
...
</Paginate>
All slots are passed a page
argument
interface Page {
data: any[]; // Array of data for the current page
start: number; // Index of first item on current page
end: number; // Index of last item on current page
size: number; // How many items per-page
total: number; // The total number of items across all pages
currentPage: number; // The current page number, starting with 1
current: number; // DEPRECATED - Use currentPage, will be removed in 0.1.0
lastPage: number; // The total number of pages
last: number; // // DEPRECATED - Use lastPage, will be removed in 0.1.0
}
<Paginate>
{page => (
...
)}
</Paginate>
Default for render for page
<Paginate>
{page => (
...
)}
</Paginate>
This slot is rendered if the page
prop is not a number or if its larger than the total number of pages Example: trying to access page 11
when there are only 10
pages
Target a specific page for an alternative render using the page number as a named slot
In this example the first page of the pagination is completely replaced with a single element <h1>First Page</h1>
<Paginate>
<first slot="1">{() => <h1>First Page</h1>}</first>
{page => (
...
)}
</Paginate>
Demo that uses the <Paginate>
, <Pagination>
and <Breadcrumb>
components to paginate an array of 100 posts from jsonplaceholder
Easily add page navigation to your page using the <Pagination>
component
// 'src/pages/posts/[page].astro'
---
const posts = await fetch('https://jsonplaceholder.typicode.com/posts')
.then(response => response.json())
---
<Paginate data={posts} size="10" page={Astro.params.page}>
{ page => (
<section>
{ page.data.map(post => (
<article>
<h2>{post.id} - {post.title}</h2>
<p>{post.body}</p>
</article>
))}
</section>
<nav>
<Pagination url="/posts" total={page.lastPage} current={page.currentPage}>
<active slot="active">{page => <span>{page.number}</span>}</active>
<span slot="disabled">...</span>
{page => <a href={page.href}>{page.number}</a>}
</Pagination>
</nav>
)}
</Paginate>
Target a page for alternative render by using the page number as a named slot
// 'src/pages/posts/[page].astro'
---
const posts = await fetch('https://jsonplaceholder.typicode.com/posts')
.then(response => response.json())
---
<Paginate data={posts} size="10" page={Astro.params.page}>
<first slot="1">{ page => (
<section>
<h1>This is the first page</h1>
{ page.data.map(post => (
<article>
<h2>{post.id} - {post.title}</h2>
<p>{post.body}</p>
</article>
))}
</section>
)}</first>
{ page => (
<section>
{ page.data.map(post => (
<article>
<h2>{post.id} - {post.title}</h2>
<p>{post.body}</p>
</article>
))}
</section>
)}
</Paginate>
Render an error page if trying to access a page number larger than the total number of pages
// 'src/pages/posts/[page].astro'
---
const posts = await fetch('https://jsonplaceholder.typicode.com/posts')
.then(response => response.json())
---
<Paginate data={posts} size="10" page={Astro.params.page}>
{ page => (
<section>
{ page.data.map(post => (
<article>
<h2>{post.id} - {post.title}</h2>
<p>{post.body}</p>
</article>
))}
</section>
)}
<section slot="error">
<p>This page does not exist</p>
</section>
</Paginate>
To paginate with an index you must use a rest route [...page]
or add the pagination to both your dynamic route and index (index.astro
and [page].astro
)
If using the <Pagination>
component for navigation you must also pass the index
prop
// 'src/pages/posts/[...page].astro'
---
const posts = await fetch('https://jsonplaceholder.typicode.com/posts')
.then(response => response.json())
---
<Paginate data={posts} size="10" page={Astro.params.page}>
{ page => (
<section>
{ page.data.map(post => (
<article>
<h2>{post.id} - {post.title}</h2>
<p>{post.body}</p>
</article>
))}
</section>
<nav>
<Pagination index url="/posts" total={page.lastPage} current={page.currentPage}>
<active slot="active">{page => <span>{page.number}</span>}</active>
<span slot="disabled">...</span>
{page => <a href={page.href}>{page.number}</a>}
</Pagination>
</nav>
)}
<section slot="error">
<p>This page does not exist</p>
</section>
</Paginate>