A highly customizable and render-less lightweight library to manage Grid related actions.
View the demo or Read the Docs
Name | Connect via |
---|---|
Tuhin Karmakar | |
Manogna Tata |
- âś… Supports Event Delegation out of the box
- âś… Has Modular Components
- âś… Bring your own CSS Styles
- âś… Override most sensible defaults with CSS-variables
- âś… Mix and Match the layout components to create your own unique version of a Grid
- âś… Uses only raw HTML tags and no 3rd party dependency
- âś… Configurable via attributes
This package uses the "sass": "^1.43.4"
Therefore, Please ensure that your
react
project hassass
installed or you can install it withnpm install --save-dev sass
oryarn add --dev sass
- Clone the repo
npm run install
oryarn install
npm run start
oryarn start
PowerGrid
PowerGridTopBar
PowerGridHeader
PowerGridBody
PowerGridFooter
PowerGridSearchBar
PowerGridDropdown
PowerGridMoreFilters
Base.scss
Body.scss
Footer.scss
TopBar.scss
Header.scss
MoreFilters.scss
These are all partial stylesheets. You can import only the bits and pieces you need. However, if you want to use all preconfigured styles, feel free to import the
PowerGrid.scss
search
sort
pagination
toggle-row-selection
dropdown-change
select-all-columns
All payloads are accessible via
event.detail
Search event is fired whenever we put contents in the search field and hit enter. Here"s the Payload:
{
"query": "String"
}
This event is fired whenever the header column is clicked. Here"s the Payload:
{
"columnName": "String",
"sortOrder": "String (ASC | DESC)"
}
This event is fired whenever the user tries to move to a previous page or the next page. Here"s the Payload:
{
"currentPage": "Number",
"mode": "String ( Backward | Forward )"
}
This is fired whenever a checkbox of a row is being selected. Here"s the Payload:
{
"rowIdx": "Number"
}
This is fired when the user tries to change the filters using the dropdown. Here"s the Payload:
{
"filter": {
"name": "String",
"value": "FilterValue"
}
}
This is fired whenever the user tries to select the checkbox in the header. Here"s the Payload:
{
"checkedState": "Boolean"
}
You can import/extend the following as per your requirements,
react-power-grid/dist/styles/PowerGrid/PowerGrid.scss
react-power-grid/dist/styles/PowerGrid/scss/_Base.scss
react-power-grid/dist/styles/PowerGrid/scss/_Body.scss
react-power-grid/dist/styles/PowerGrid/scss/_Footer.scss
react-power-grid/dist/styles/PowerGrid/scss/_Header.scss
react-power-grid/dist/styles/PowerGrid/scss/_MoreFilters.scss
react-power-grid/dist/styles/PowerGrid/scss/_TopBar.scss
react-power-grid/dist/styles/PowerGrid/PowerGrid.scss
react-power-grid/dist/styles/PowerGrid/css/Base.css
react-power-grid/dist/styles/PowerGrid/css/Body.css
react-power-grid/dist/styles/PowerGrid/css/Footer.css
react-power-grid/dist/styles/PowerGrid/css/Header.css
react-power-grid/dist/styles/PowerGrid/css/MoreFilters.css
react-power-grid/dist/styles/PowerGrid/css/TopBar.css
You can Create your own css/scss files and put the structure like this
.power-grid {
nav {
// Put Your custom styles for top bar
}
header {
// Put Your custom styles for header
}
main {
// Put Your custom styles for grid body
}
footer {
// Put Your custom styles for grid footer
}
}
Sample Usage:
<PowerGrid
loading={Boolean}
topBar={<ReactComponent/>}
gridHeader={<ReactComponent/>}
gridBody={<ReactComponent/>}
gridFooter={<ReactComponent/>}
loadingComponent={<ReactComponent/>}
/>
More Info on Props:
{
"loading": "This is used to show/hide the spinner while fetching data from the server",
"topBar": "Any React Component || <PowerGridTopBar />",
"gridHeader": "Any React Component || <PowerGridHeader />",
"gridBody": "Any React Component || <PowerGridBody />",
"gridFooter": "Any React Component || <PowerGridFooter />",
"loadingComponent": "Any React Component || <Spinner />"
}
To use the default styling for this component please import/extend react-power-grid/dist/styles/PowerGrid/PowerGrid.scss
Note: You can always have your custom components in place of pre-baked ones.
Sample Usage:
<PowerGridTopBar
filters={topBarFilters}
moreFilters={<ReactComponent/>}
searchBar={<ReactComponent/>}
/>
More Info on Props:
{
"filters": "This is a JSON Array Of Objects which is used to provide filters that can be applied on the PowerGrid.",
"moreFilters": "<PowerGridMoreFilters /> || Any React component",
"searchBar": "<PowerGridSearchBar /> || Any React Component."
}
Example of how filters Array looks like:
const filter = [
{
"name": "First Filter",
"options": [
"Option 1",
"Option 2",
"Option 4"
],
"allowMultiSelect": true
},
{
"name": "Second Filter",
"options": [
"Option 1",
"Option 2",
"Option 4"
],
"allowMultiSelect": false
}
// put more filters like this
]
In Case if you want to Bring your Own Component while using the same Object Syntax, You can do so with the following:
const filter = [
{
"name": "Custom Filter Implementation",
"options": [
// EVERYTHING WILL BE IGNORED
],
"allowMultiSelect": "THIS WILL BE IGNORED",
"custom": <ReactComponent/>
},
]
In the Custom React Component, you can do anything you want but, remember to add a custom event emission in the onchange section. For example,
const emitCustomEvent = ({target}) => {
target.dispatchEvent(new CustomEvent('your-own-on-change-event-name', {
bubbles: true,
detail: {
filter: {
name: item.name,
value: target.value
}
}
})
)
}
Then you can add your own handler to it
parentNode.addEventListener('your-own-on-change-event-name', ({detail}) => {
doSomething(detail)
})
Sample Usage:
<PowerGridHeader columns={gridHeaderColumns}/>
More Info on Props:
{
"columns": "This is an array of Objects that consists of header columns"
}
The gridHeaderColumns
is defined as:
const gridHeaderColumns = ["Column 1", "Column 2", "Column 3", "Column N"]
Sample Usage:
<PowerGridBody gridData={gridBodyData}
More Info on Props:
{
"gridData": "This is a multidimensional array consisting the data that needs to be inserted in the Grid."
}
Example of how gridBodyData looks like:
const gridBodyData = [
[true, "col 1", "col 2", "col 3"], // row 1
[true, "col 1", "col 2", "col 3"], // row 1
[true, "col 1", "col 2", "col 3"], // row 1
]
/* The Generic Structure is :
[
[ InputCheckBoxValue (True / False), Column 1, Column 2, ..., Column N], // ROW 1
[ InputCheckBoxValue (True / False), Column 1, Column 2, ..., Column N], // ROW 2
]
*/
Sample Usage:
<PowerGridFooter
hasNext={Boolean}
hasPrevious={Boolean}
currentPage={Number}
totalPages={Number}
/>
More Info on Props:
{
"hasNext": "This is used to enable/disable the next button in Footer. When False, next button is disabled.",
"hasPrevious": "This is used to enable/disable the prev button in Footer. When False, prev button is disabled.",
"currentPage": "This shows the current page number",
"totalPages": "this shows the total number of pages"
}
Sample Usage:
<PowerGridMoreFilters>
{children}
</PowerGridMoreFilters>
More Info on Props:
{
"children": "You can put any React Component here. You can also use PowerGridDropdown or PowerGridSearchBar or any custom react component."
}
However, make sure to dispatch the following event while implementing your own version.
const emitCustomEvent = ({target}) => {
target.dispatchEvent(new CustomEvent('more-filter-change', {
bubbles: true,
detail: {
filter: {
name: item.name,
value: target.value
}
}
}))
}
Then you can add your own handler to it
parentNode.addEventListener('more-filter-change', ({detail}) => {
doSomething(detail)
})
Sample Usage:
<PowerGridSearchBar/>
Sample Usage:
<PowerGridDropdown item={item}/>
More Info on Props:
{
"item": {
"name": "FilterName",
"options": [
"Option Value 1",
"Option Value 2"
],
"allowMultiSelect": "Boolean"
}
}
For Example, we can create a PowerGrid component as follows:
<PowerGrid
loading={isDataLoading}
topBar={
<PowerGridTopBar
filters={filter}
moreFilters={<PowerGridMoreFilters>{getMoreFilters()}</PowerGridMoreFilters>}
searchBar={<PowerGridSearchBar/>}
/>
}
gridHeader={<PowerGridHeader columns={headerColumns}/>}
gridBody={<PowerGridBody gridData={gridData}/>}
gridFooter={
<PowerGridFooter
hasNext={hasNext}
hasPrevious={hasPrevious}
currentPage={1}
totalPages={1}
/>
}
/>
import React, {useEffect, useRef, useState} from 'react'
import {gridBodyData, gridHeaderColumns, topBarFilters} from './seed/data'
import {
PowerGrid,
PowerGridBody,
PowerGridDropdown,
PowerGridFooter,
PowerGridHeader,
PowerGridMoreFilters,
PowerGridSearchBar,
PowerGridTopBar,
} from 'react-power-grid'
import 'react-power-grid/dist/styles/PowerGrid/PowerGrid.scss'
const App = () => {
const powerTableContainer = useRef(null)
const [emittedEvent, setEmittedEvent] = useState(null)
const [isDataLoading] = useState(false)
const [headerColumns] = useState(gridHeaderColumns)
const [gridData, setGridData] = useState(gridBodyData)
const [hasNext] = useState(true)
const [hasPrevious] = useState(false)
const [filter] = useState(topBarFilters)
const [moreFilters] = useState(topBarFilters)
const logEventDetails = ({type, detail}) => {
setEmittedEvent({
type, detail
})
console.log(type, detail)
}
const handleIndividualRowSelection = (evt) => {
logEventDetails(evt)
const rowIdx = evt.detail.rowIdx
const updatedGridData = [...gridData]
updatedGridData[rowIdx][0] = !updatedGridData[rowIdx][0]
setGridData(updatedGridData)
}
const handleAllRowSelection = (evt) => {
logEventDetails(evt)
const checkedState = evt.detail.checkedState
setGridData(gridData.map(item => {
item[0] = checkedState
return item
}))
}
const showEventDetails = () => (
<pre>Event Type: {emittedEvent?.type}<br/>Event Details: {JSON.stringify(emittedEvent?.detail)}</pre>
)
const getMoreFilters = () =>
moreFilters.map((item) => (
<li key={item.name}>
{item?.custom || <PowerGridDropdown item={item}/>}
</li>
))
useEffect(() => {
powerTableContainer?.current.addEventListener('sort', logEventDetails)
powerTableContainer?.current.addEventListener('pagination', logEventDetails)
powerTableContainer?.current.addEventListener('search', logEventDetails)
powerTableContainer?.current.addEventListener('toggle-row-selection', handleIndividualRowSelection)
powerTableContainer?.current.addEventListener('select-all-columns', handleAllRowSelection)
powerTableContainer?.current.addEventListener('dropdown-change', logEventDetails)
}, [])
useEffect(() => () => {
powerTableContainer?.current.removeEventListener('sort', logEventDetails)
powerTableContainer?.current.removeEventListener('pagination', logEventDetails)
powerTableContainer?.current.removeEventListener('search', logEventDetails)
powerTableContainer?.current.removeEventListener('toggle-row-selection', handleIndividualRowSelection)
powerTableContainer?.current.removeEventListener('select-all-columns', handleAllRowSelection)
powerTableContainer?.current.removeEventListener('dropdown-change', logEventDetails)
}, [])
return (
<div className="power-grid-demo">
<nav>
<h1>React Power Grid</h1>
<a href="https://tuhinkarmakar3882.github.io/react-power-grid/" target="_blank" rel="noreferrer">
<button>View Docs</button>
</a>
</nav>
<main ref={powerTableContainer}>
<PowerGrid
loading={isDataLoading}
topBar={
<PowerGridTopBar
filters={filter}
moreFilters={<PowerGridMoreFilters>{getMoreFilters()}</PowerGridMoreFilters>}
searchBar={<PowerGridSearchBar/>}
/>
}
gridHeader={<PowerGridHeader columns={headerColumns}/>}
gridBody={<PowerGridBody gridData={gridData}/>}
gridFooter={
<PowerGridFooter
hasNext={hasNext}
hasPrevious={hasPrevious}
currentPage={1}
totalPages={1}
/>
}
/>
</main>
</div>
)
}
export default App
A highly customizable and render-less lightweight library to manage Grid related actions.
Name | Connect via |
---|---|
Tuhin Karmakar | |
Manogna Tata |