tremor
tremor copied to clipboard
How to add pagination to the table?
Is there a way to tremor to handle the pagination or do we need to handle it manually?
Awesome library, keep up the good work
Hey @luis-cruzt, tremor's table does not support pagination out of the box, you would have to implement this feature yourself. Thanks for using tremor & happy coding 😁
Any update? Any help with pagination?
This feature would be great
Heya! I am not convinced that a general pagination component makes sense within the table today.
A few thoughts:
- Would be it a "123 ... 789" or a "show more" component?
- Should there be a page input field or just left/right buttons?
- Adding a skip to the end/start button?
There are so many paths ideal pagination could look like. In light of this, I would leave it to the developer to create a pagination specifically tailored to the use case.
One more thing, adding pagination e.g. a property to specify defaultPageSize={n}, so that the table only displays n rows, and adding as many pages as needed. This would change the Table API significantly, basically reducing the table to one component because you have to take care of the pagination logic throughout the component.
Here's an example of how a custom pagination could look like:
import React, { useState } from 'react';
const demoData = [
{ id: 1, name: 'John Doe', age: 25 },
{ id: 2, name: 'Jane Doe', age: 30 },
{ id: 3, name: 'Bob Smith', age: 35 },
{ id: 4, name: 'Alice Johnson', age: 40 },
{ id: 5, name: 'Tom Davis', age: 45 },
{ id: 6, name: 'Sara Lee', age: 50 },
{ id: 7, name: 'Mike Johnson', age: 55 },
{ id: 8, name: 'Mary Johnson', age: 60 },
{ id: 9, name: 'David Smith', age: 65 },
{ id: 10, name: 'Lisa Davis', age: 70 },
{ id: 11, name: 'Mark Johnson', age: 75 },
{ id: 12, name: 'Linda Smith', age: 80 },
{ id: 13, name: 'Peter Lee', age: 85 },
]
function Table({ data, defaultPageSize }) {
const [currentPage, setCurrentPage] = useState(1);
function renderTableHeader() {
return (
<tr>
<th>ID</th>
<th>Name</th>
<th>Age</th>
{data[0]?.email && <th>Email</th>}
</tr>
);
}
function renderTableData() {
if (!defaultPageSize) {
return data.map((item, index) => {
return (
<tr key={index}>
<td>{item.id}</td>
<td>{item.name}</td>
<td>{item.age}</td>
{item.email && <td>{item.email}</td>}
</tr>
);
});
}
const startIndex = (currentPage - 1) * defaultPageSize;
const endIndex = startIndex + defaultPageSize;
return data.slice(startIndex, endIndex).map((item, index) => {
return (
<tr key={index}>
<td>{item.id}</td>
<td>{item.name}</td>
<td>{item.age}</td>
{item.email && <td>{item.email}</td>}
</tr>
);
});
}
function renderPagination() {
if (!defaultPageSize) return null;
const totalPages = Math.ceil(data.length / defaultPageSize);
const startItem = (currentPage - 1) * defaultPageSize + 1;
const endItem = Math.min(currentPage * defaultPageSize, data.length);
return (
<div className="flex justify-between items-center">
<div>
Showing {startItem} – {endItem} of {data.length}
</div>
<div className="flex">
<button
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-l focus:outline-none"
disabled={currentPage === 1}
onClick={() => setCurrentPage(currentPage - 1)}
>
← Prev
</button>
<button
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-r focus:outline-none"
disabled={currentPage === totalPages}
onClick={() => setCurrentPage(currentPage + 1)}
>
Next →
</button>
</div>
</div>
);
}
return (
<div>
<table className="table-auto">
<thead>{renderTableHeader()}</thead>
<tbody>{renderTableData()}</tbody>
</table>
{renderPagination()}
</div>
);
}