-
Notifications
You must be signed in to change notification settings - Fork 4
Paginate
This is the SSR component version of Astro's SSG paginate()
method
Features:
- Paginate an array of data
- Compatible with indexes
- Compatible with
<Pagination>
component for page navigation - Alternatively render a specific page using the page number as a named slot
-
New: Render an 'error' page using the
error
slot if a page number that doesn't exist is accessed
Example:
---
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>
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>
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
current: number; // The current page number, starting with 1
last: number; // The total number of pages
}
<Paginate>
{page => (
...
)}
</Paginate>
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.last} current={page.current}>
<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 add the <Paginate>
component to the index (index.astro
) of your dynamic [page].astro
route
If using the <Pagination>
component for navigation you must pass the index
prop
// 'src/pages/posts/index.astro' and '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.last} current={page.current}>
<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>