The latest version of the @preaction/bootstrap-clips package now has a reusable, sortable, filterable, searchable, pageable, and extendable Table component.
That's a lot of adjectives to cover. Let's dive in!
Getting Started
yarn add --dev @preaction/bootstrap-clips \
bootstrap \
@popperjs/core
or:
npm install --save-dev @preaction/bootstrap-clips \
bootstrap \
@popperjs/core
Note: bootstrap is a peerDependency of this library, and @popperjs/core is a peerDependency of bootstrap.
Example: Users Table
The following example will render a table from the JSON Placeholder /users
resource. In addition to the id
, name
, email
, phone
, and website
attributes, I want the company
attribute to reflect company.name
from the JSON data. An additional column should also be added for a "View" button. The email and website columns should be rendered with hyperlinks. Each column should be sortable (aside from "View"), filterable, and searchable. By default, the users should be sorted by their id
attribute.
import { Table } from '@preaction/bootstrap-clips'
function UserTableExample() {
const [userHeaders] = React.useState(
new Map()
.set('view', 'View')
.set('id', 'ID')
.set('name', 'Name')
.set('email', 'Email')
.set('phone', 'Phone')
.set('website', 'Website')
.set('company', 'Company')
)
const [users, setUsers] = React.useState([])
// fetch rows from API
React.useEffect(async () => {
const response = await fetch('https://jsonplaceholder.typicode.com/users')
if (response.status === 200) {
const data = await response.json()
const users = []
for (let u = 0; u < data.length; u++) {
users.push(Object.assign(data[u], { company: data[u].company.name }))
}
setUsers(users)
}
}, [])
// render
return (
<div className='app'>
<h4>User Table</h4>
<hr />
<Table
headers={userHeaders}
rows={users}
theme='light'
hover
responsive
rowKey='id'
extendRow={row => ({
email: (
<a href={`mailto:${row.email}`} onClick={e => e.preventDefault()}>
{row.email}
</a>
),
view: (
<button
type='button'
className='btn btn-sm btn-secondary'
onClick={() => console.log(row)}>
View
</button>
),
website: (
<a
href={`https://${row.website}`}
target='_blank'
rel='noopener noreferrer'
onClick={e => e.preventDefault()}>
{row.website}
</a>
)
})}
filter
sort={['id', 'name', 'email', 'phone', 'website', 'company']}
search
defaultSortKey='id'
/>
</div>
)
}
<UserTableExample />
This works pretty well, but how does it handle a larger dataset?
Example: Photo Table
The following will render a table for all 5,000 of the items in JSON Placeholder's /photos
resource, using pagination of the number specified (in this case, 4). I want only the id
, and title
columns to be sortable, and only the title
column to be searchable. Also, instead of just showing you the url
for each row, I want it to render the image's thumbnail within a link that opens the full size image in a new window.
import { Table } from '@preaction/bootstrap-clips'
function PhotoTableExample() {
const [userHeaders] = React.useState(
new Map().set('id', 'ID').set('title', 'Title').set('url', 'Image')
)
const [photos, setPhotos] = React.useState([])
// fetch rows from API
React.useEffect(async () => {
const response = await fetch('https://jsonplaceholder.typicode.com/photos')
if (response.status === 200) {
const data = await response.json()
setPhotos(data)
}
}, [])
// render
return (
<div className='app'>
<h4>Photo Table</h4>
<hr />
<Table
headers={userHeaders}
rows={photos}
theme='light'
striped
responsive
compact
rowKey='id'
sort={['id', 'title']}
search={['title']}
defaultSortKey='id'
extendRow={row => ({
url: (
<div
style={{ width: '5rem', height: '5rem' }}
className='img-thumbnail'>
<a href={row.url} target='_blank' rel='noopener noreferrer'>
<img src={row.thumbnailUrl} width='100%' height='100%' />
</a>
</div>
)
})}
pagination={4}
/>
</div>
)
}
<PhotoTableExample />
There are multiple ways to change pages. You can use the previous/next buttons or change the number input, but my favorite thing about this is the range slider. I like it a lot better than numbered buttons or links for paginated navigation because the interface is consistent regardless of
the number of pages. I'm also quite proud of how blazingly fast the table re-renders when sliding this back and forth.
You can play with these examples along with my other components in this library directly within the documentation, which was generated using React Styleguidist.
Top comments (1)
Thank you for sharing this. Exactly what I was looking for 👌❤️🦄