gridact
v4.0.0
Published
Your Excellent React Grid Component
Downloads
6
Maintainers
Readme
Gridact
Your Excellent React Grid Component
Gridact is React component for displaying large datasets in table supporting
- filtering
- sorting
- paging
- custom page lengths with initial set
- custom row classes based on row data
- individual columns definitions
- column name
- sortable, editable,
- hidden, width, table head class
- custom cell rendering (based on cell and row data)
- custom cell class rendering based on row data
- inline editing with server side processing
- edit cells
- add and remove rows
- custom allowed values and characters
- error messages
##Live demo on CodeSandBox
Please open the project in window (https://89khh.codesandbox.io/), not in CodeSandBox browser, does not work.
##Changelog 3.1.0 (2022-08-18)
- optimized version, a lot of changes in code, coded splitted into more modules for better readability.
- added cross-application gridactContext, which made it much better administratable.
- primaryKey property no longer user, module calculates its own.
##Changelog 2.5.0
- new format of data from edit, simplier
{newValue, column, row}
From Row you can find whatever identification you need. Remove primary_key property of GridAct - you do not need this anymore
##Changelog 2.1.0
- editable option in column definitions can now be function (e.g. you want to edit only if some condition is met)
- enhanced sorting, corrected sort of empty (null) values
- title option now available in columns definition
##Changelog 2.0.0
- Further optimized re-render evaluation on row (propsAreEqual.js)
- Code readability improved
- Access to filtered rows, so you can e.g. calculate total sums to your table header (look at setFilteredData prop)
##Changelog 1.0.0
- Many small bugs fixed
- Changed Icons to Font Awesome
- initial sort (initSort) now possible
- mainTableContainerClass for styling whole table container
GridAct
I have done my best to optimize rendering, so the work is for user very good with rendering displayed table with 2000 cells (100 rows with 20 columns) in ~200 ms or 10000 cells in ~800 ms. (Change page to page render time.) Render speed is not very much affected with total size of data, but with data displayed. For user experience I recommend not to allow page longer then 100 rows with 20 columns table.
Gridact component is result of my experience working with Microsoft Excel as an user and jQuery DataTables as developer. Datatables taught me to love data in JavaScript and that's a big thanks to Allan Jardine. This motivated me to create Gridact.
This is my first public React Component, I'll be really glad for any feedback and I'll do my best to satisfy any of your requests. Thanks.
##Contact Email me at filip (a) debef . com Send me a Messenger message
Installation
Nothing but easy.
npm i gridact
These modules must be installed in parent component. ~~Bootstrap must be imported in whichever parent component~~. (Bootstrap removed in version 0.6.0)
For proper function of error messages, append <div id="modalEl"></div>
to your body
of index.html
.
Basic configuration
The basic configuration is pretty simple. Just import Gridact module and pass data and some configuration:
import Gridact from 'gridact'
import React from 'react';
const App = () => {
const [data, setData] = useState();
useEffect(() => {
yourApi().then(yourData => {
setData(yourData)}
)}, [])
<Gridact
data={data}
colDefs={tableColsDef}
wrapperDivClass={['table-responsive', 'col-xl-12']}
tableClasses={['table', 'table-sm', 'table-striped', 'text-nowrap', 'table-bordered']}
pagingOptions={[5, 10, 20, 50, 100]}
fnRowClass={(row) => {
if (row.name_original) {
if (row.name_original.includes('X')) return 'font-weight-bold text-danger';
return undefined;
}
return undefined;
}
}
serverSideEdit={editData => YourApi('yourUri', editData)
}
showFilter
addRemove
pageSelector
pagingSelector
searchPlaceHolder="Search..."
onEnterMoveDown={false}
/>
Gridact props
data
Type: Array of Objects <mandatory>
[{col1: val, col2: val,...}, {col1: val, col2: val,...},...]
wrapperDivClass
Type: Array, String <option>
Props is joined to final classNames classNames=wrapperDivClass.join(' ')
Final table is wrapped in div - main reason was enabling responsiveness in bootstraps, what requires table's outer div.
For table responsiveness, use at least 'table-responsive col'
tableClasses
Type: Array | String <option>
Props is joined to final classNames classNames=wrapperDivClass.join(' ')
Best use with boostrap's table classes. E.g. ['table', 'table-sm', 'table-striped', 'text-nowrap', 'table-bordered']
mainTableContainerClass
Type: String Main container class, in this container is wrapped table and all controll items. (Paging, search,...)
###tableCellClass ###
Type: String <option>
Easy cell styling, changes style of th
and td
cells in table.
###setFilteredData ###
Type: Function <option>
Function will be passed with filtered dataset Array
- subset of originaly provided table data.
Necessary e.g. for sum of filtered columns.
pagingOptions
Type: Array <option>
Page length options. Will always be sorted numerically, first value will be initials.
Example: [20,10,50,100]
- paging options will be [10,20,50,100]
- initial set will be [20]
.
If undefined, default paging is [10, 20, 50]
.
fnRowClass
Type: String | Array | function <option> String or Array of classNames If function is provided, it is passed row data. Must return String or Array. Used e.g. for coloring whole row based on row data.
fnRowClass
Type: String | Array | function <option> String or Array of classNames If function is provided, it is passed row data. Must return String or Array. Used e.g. for coloring whole row based on row data.
fnCellClass
Type: String | Array | function <option> String or Array of classNames If function is provided, it is passed row data. Must return String or Array. Used e.g. for coloring cells based on row data.
initSort
Type: Object <option> Initial sort of table in object {col: colName, dir: 'asc' | 'desc' }
serverSideEdit
AcceptedValues: function <mandatory> if editable columns Function is provided with Object according to selected operation.
Objects passed to function are based on operation
edit
Cell edit
Passed argument: {operation: 'edit', newValue: {[editedColumn]: [newValue]}, row: [rowData]}}
Required response: Promise resolved with {data: [updatedRow]}
If you want to validate data server-side, you can response with {error: errorMsg}
, where errorMsg
is string,
which will be displayed in small overlay next to edited cell.
If error
is in response, data will not be updated in table, previous value will be restored.
new
Add new row
Passed argument: {operation: 'new'}
Required response: Promise resolved with {data: [newRow]}
In newRow, primary_key must not be null
.
delete
Delete row, where is focused cell.
Passed argument: {operation: 'delete', row: [rowData]}
Required response: {data: 1}
If value of data
key is < 1, row will not be deleted in table.
click
You can choose for clicking on cell value and change it on click.
Passed argument: {operation: 'edit', newValue: {[editedColumn]: [oldValue]}, row: [rowData]}}
You decide, how the value should change on click.
Response should be {data: [updatedRow]}
showFilter, addRemove, pageSelector, pagingSelector
Type: Boolean <option> Shows/hide filter (search field), add remove row buttons, page selector (what page is displayed), paging selector (page length)
searchPlaceHolder
Type: String <option> Default: "Search..."
onEnterMoveDown
Type: Boolean
If true
, on enter
cursor moves down. otherwise moves right.
colDefs
Columns definitions Type: Object <mandatory>
colDefs is object, where keys are column codes, values are column definitions itsels in Object.
{line_id: {
cellRender: v => v,
name: 'ID',
editable: false,
// filterEditValue: function | regexp of chars to filter out (newValue.prototype.replace(regexp, '')
// function must return Boolean
filterEditValue: (newValue, curCellValue, row) => (newValue.replace(/[{]|[}]|[<]|[>]|[\\]|[/]/g, '')),
// filterEditValue: function which returns true to allow or false for disable char
// regexp of chars allowed (newValue.prototype.match(regexp))
filterEditChar: (char, cellValue, row) => char.match(/[a-zA-ZščřžýáíéóúůďťňĎŇŤŠČŘŽÝÁÍÉÚŮ0-9 ]/g),
sortable: true,
filterable: true,
resizable: true,
width: 80,
hidden: false
}
},
...}
Column definition properties
cellRender
Type: function | string <option>
If undefined, the cell is rendered with value provided in data.
If string is provided, the string is returned.
Function is passed cell_value
and row_data
. This means, you can render the cell based on other values in row.
Example:
cellRender: (cellValue, rowData) => if (rowData.volume) > 10 return 'TOO HIGH' else return cellValue
Special attention on circular objects as cellRender:
You can pass function returning React Components to cellRender (e.g. input select
in table head). As GridAct uses
on row level custom property change evalution (React.memo, or formerly known as ComponentShouldUpdate), if you pass
in cellRender circular objects other then React Component , application with crash. For common use this should not
limit you.
tableHead (!changed in version 0.6.0 - previously "name")
Type: string <mandatory> Name of column in table header
width
Type: integer <option>
Set width of current column. Default <td>
css style is overflow: hidden
.
editable
Type: Boolean | Function(cellValue, rowData)
<option>
Column cells will be editable. If value is not Boolean or Function, it is evaluated as Boolean(providedValue)
sortable
Type: Boolean <option> Column cells will be sortable. If
hidden
Type: Boolean <option> Column will be hidden. Usefull when you want to calculate cell value from multiple columns or style cell based on data from other columns but the other columns you do not want to show.
title
Type: Boolean | Function(cellValue, rowData)
<option>
Title (small hint over cell), e.g. when not whole content is visible, or when you want to comment the cell content.
Default is false, when set to True
, the content of cell is used.
cellClass
Type: String | Array | function <option>
Class used for every cell in this column.
String or Array of classNames
If function is provided, it is passed (cellValue, rowData)
. Must return String or Array.
Used e.g. for coloring whole column based on data of given cell or other cells in row.
thClass
Type: String | Array | function <option>
Class used for every cell in this column.
String or Array of classNames
If function is provided, it is passed (cellValue, rowData)
. Must return String or Array.
Used e.g. for coloring whole column based on data of given cell or other cells in row.
As the inline edit is build upon contentEditable, I paid a lot of attention to sanitize input text to avoid XSS. There two filter options for values users can write to cell.
filterEditChar
Type: RegExp | function <optional>
This option is applied directly onKeyPress event - it does not let user write the characters you specify.
If RegExp is provided, it is passed to character_typed.match()
.
Function is passed three arguments: (character_typed, cell_value_before_edit, row_data)
Must return true
or false
.
True = character is allowed, false = disallowed.
Default value is
(char, CellValue, rowData) => return char.match(/[a-zA-ZščřžýáíéóúůďťňĎŇŤŠČŘŽÝÁÍÉÚŮ0-9 ]/);
Allowed are only alphanumeric characters included Czech ones.
filterEditValue
Type: RegExp | function <optional>
Because above mentioned option does not block pasting from clipboard, and I didn't want to forbid it generally,
we have to check the final value user sends to your serverSideEdit function and which will be displayed in table.
As this is potential XSS risc, pay close attention to this function.
Function is passed three arguments: (new_cell_value, cell_value_before_edit, row_data)
Must return sanitized string.
Default value is
(newValue, cellValue, row) => (newValue.replace(/[{]|[}]|[<]|[>]|[\\]|[/]/g, ''))
If RegExp is provided, it is passed to newValue.replace(RegExp, '')
Styling
You can fully style with own classes. See custom styles.css
. GridAct is built on CSS grid.
Further development
I'll be glad if you leave me a message. What you miss, what you want, what you like. What can be added in the future:
customizable icons
custom placement of Search, add / remove buttons and paging options.
better page selector