Skip to content

flipbyte/redux-datatable

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@flipbyte/redux-datatable

Developed by Flipbyte

npm package Codacy Badge

Datatable built using React and Redux to fetch JSON data asynchronously using REST API.

  • Filterable columns by date ranges, numeric ranges and text.
  • Pagination
  • Sortable columns
  • Configurable column widths
  • Editable table
  • Built in windowing to handle large dataset with thousands of rows
  • Customizable limiter options
  • Customizable toolbar with the ability to add custom renderers
  • Easily configurable layout
  • Custom row level actions
  • Thunks to handle custom mass or row actions externally.
  • Compatible with normalizr to handle externally managed states
  • Easily styleable with styled-components and/or external css.
  • Show or hide columns dynamically using the Columns item in the toolbar.

Installation

Run the following command to install using npm

npm i @flipbyte/redux-datatable

Usage

Add the table reducer and epics to your store

// Get the table reducer and epics as follows
import { reducer, epics } from '@flipbyte/redux-datatable';

// Add the above reducer and epics to your store.

Preparing your table config object

{
    name: 'your_table_name', // this is the key used to set your table data inside the table reducer
    height: 400,
    rowHeight: 50,
    editing: false,
    primaryKey: 'id',
    noResultsMessage: 'No row(s) found',
    routes: { // You can add other routes and handle them using custom actions.
        get: { // The route used to fetch data and it's params
            route: '/{your_route}',
            sort: 'id',
            dir: 'asc',
            resultPath: {
                data: 'data'
            },
            params: {
                ...your_params_key_value_pair
            }
        },
        ...
    },
    entity: { // optional. Check example code in /demo.
        state: '{your state path}',
        responseSchema: // normalizr schema,
        schema: // normal;izr schema
    },
    layout: [
        ['Editable'],
        ['MassActions', 'SimpleButton', 'ResetFilters', 'Spacer', 'Print', 'Columns'],
        ['Limiter', 'Spacer', 'ResultCount', 'Spacer', 'Pages'],
        [{ id: 'Table', layout: [
            ['Header'],
            ['Filters'],
            ['Body'],
            ['Header']
        ]}],
        ['Limiter', 'Spacer', 'ResultCount', 'Spacer', 'Pages'],
    ],
    components: {
        Header: {
            rowClassName: 'your custom class names',
            colClassName: 'your custom class names',
            className: 'your custom class names',
        },
        Body: {
            rowClassName: 'your custom class names',
            colClassName: 'your custom class names',
            className: 'your custom class names',
        },
        Filters: {
            rowClassName: 'your custom class names',
            colClassName: 'your custom class names',
            className: 'your custom class names',
        },
        Loader: {
            styles: {
                mask: { ... },
                spinner: { ... }
            }
        },
        ResultCount: {
            className: 'your custom class names',
            styles: { ... }
        },
        Pages: {
            firstClassName: 'your custom class names',
            lastClassName: 'your custom class names',
            nextClassName: 'your custom class names',
            prevClassName: 'your custom class names',
            pageNumberClassName: 'your custom class names',
            activeClassName: 'your custom class names',
            styles: {
                first: { ... },
                last: { ... },
                previous: { ... },
                next: { ... },
                pageNumber: { ... },
            }
        },
        Editable: {
            type: 'editable',
            labels: {
                show: 'Make editable',
                hide: 'Hide editable',
                save: 'Save',
            },
            classNames: {
                show: 'your custom class names',
                hide: 'your custom class names',
                save: 'your custom class names',
            },
            save: ( config ) => ( dispatch, getState ) => {
                const tableState = getState()[config.reducerName][config.name];
                console.log('toolbar save click with modified data', config, tableState.modified);
                config.action(MODIFY_DATA)({ clear: true });
                // Dispatch MODIFY_DATA action with clear: true, to reset the modified data
                // Dispatch REQUEST_DATA action "config.action(REQUEST_DATA)" to refresh data.
            },
            styles: {
                show: { ... },
                hide: { ... },
                save: { ... }
            }
            // renderer: ( props ) => { ... }
        },
        MassActions: {
            name: 'actions',
            label: 'Actions',
            id: 'dropdown',
            className: 'your custom class names',
            btnClassName: 'your custom class names',
            menuClassName: 'your custom class names',
            menuItemClassName: 'your custom class names',
            activeClassName: 'your custom class names',
            styles: {
                button: { ... },
                dropdownMenu: { ... },
                dropdownItem: { ... }
            }
            options: [{
                type: 'action',
                name: 'delete',
                label: 'Delete',
                styles: { ... },
                thunk: ( config ) => ( dispatch, getState ) => {
                    // Get current table state.
                    const tableState = getState()[config.reducerName][config.name];
                    console.log(config, tableState);
                    console.log(getItemIds(tableState.selection, tableState.items, config.primaryKey/*, config.entity.schema*/))
                    confirm('Are your sure you want to delete the selected items?')
                        ? console.log('delete items', config, getState(), tableState)
                        : console.log(false);

                    // Filter your selected item ids here for deletion
                    // You can find the selection data in the selection key of the tableState.
                    // When all:true, exclude the ids in the selected object with value false and vice versa.
                }
            }, {
                type: 'action',
                name: 'edit',
                label: 'Edit this field',
            }, ...]
        },
        SimpleButton: {
            type: 'button',
            label: 'Simple Button',
            className: 'your custom class names',
            thunk: ( config ) => ( dispatch, getState ) => { ... },
            styles: { ... }
        },
        ResetFilters: {
            type: 'reset-filters',
            label: 'Reset Filters',
            className: 'your custom class names',
            styles: { ... }
        },
        Print: {
            type: 'print',
            label: 'Print Table',
            className: 'your custom class names',
            styles: { ... }
        },
        Columns: {
            name: 'columns',
            type: 'columns',
            label: 'Columns',
            visible: true,
            className: 'your custom class names',
            btnClassName: 'your custom class names',
            menuClassName: 'your custom class names',
            menuItemClassName: 'your custom class names',
            activeClassName: 'your custom class names',
            styles: {
                button: { ... },
                dropdownMenu: { ... },
                dropdownItem: { ... }
            }
        },
        Limiter: {
            type: 'limiter',
            options: [10, 20, 50, 200, 2000, 0],
            default: 200,
            className: 'your custom class names',
            selectClassName: 'your custom class names',
            styles: { ... }
        },
        Table: {
            className: 'your custom class names',
            styles: {
                table: { ... },
                thead: { ... },
                tbody: { ... },
                filters: { ... },
                tr: {
                    header: { ... },
                    filters: { ... },
                    body: { ... }
                },
                th: { ... },
                td: {
                    filters: { ... },
                    body: { ... }
                }
            },
            columns: [{
                name: 'id',
                label: '',
                sortable: false,
                type: 'selection',
                width: 50,
            }, {
                label: 'ID',
                type: 'number',
                name: 'id',
                sortable: true,
                width: 150,
                filterable: true,
                sortable: true,
            }, {
                label: "Status",
                type: "options",
                name: "status",
                sortable: true,
                filterable: true,
                textAlign: "center",
                options: {
                    "published": {
                        label: "Published"
                    },
                    "draft": {
                        label: "Draft"
                    },
                    "archived": {
                        label: "Archived"
                    },
                    ...
                }
            }, {
                label: 'Avatar',
                type: 'image',
                name: 'avatar',
                sortable: false,
                textAlign: 'center',
                width: 200,
                filterable: false,
                imgHeight: 50
            }, {
                label: 'First Name',
                type: 'string',
                name: 'first_name',
                sortable: true,
                textAlign: 'text-left',
                width: 200,
                filterable: true,
            }, {
                label: 'Actions',
                type: 'actions',
                name: 'actions',
                width: 100,
                items: [{
                    type: 'action',
                    name: 'edit',
                    label: 'Edit',
                    btnClass: 'btn btn-secondary',
                    icon: 'edit',
                    thunk: ( payload ) => ( dispatch, getState ) => {
                        console.log('edit', payload, getState());
                    },
                    style: { ... }
                }, {
                    type: 'action',
                    name: 'delete',
                    label: 'Delete',
                    icon: 'trash-alt',
                    thunk: ( payload ) => ( dispatch, getState ) => {
                        confirm("Are your sure you want to delete this page?")
                            ? console.log('delete', getState())
                            : console.log(false);
                    },
                    style: { ... }
                },
            	...
            	]
            },
            ...
            ]
        }
    }
}

Render table component

import ReduxDatatable from '@flipbyte/redux-datatable';

const YourComponent = () =>
	<ReduxDatatable
		reducerName={ /* The key used while combining reducers in the store */ }
		config={ /*your table config object*/ }
	/>

Table config props

Key Type Required Default Description
name string true - key in the row data whose value needs to be loaded for the column (does not have to be unique)
height integer true - The maximum height of the table
rowHeight integer true - The maximum height of each table body row
routes object true - Routes definition to fetch data and other custom routes config for custom handling (Check below)
components object true - All the components required for your table
entity object false - Normalizr specification. Check below for details.
layout array true - The layout of your table
editing boolean false false Set the default state of the table to be in editing mode
primaryKey string true - Set the primary key column of the table for actions like editing.
noResultsMessage string true - Set the message to be displayed when table is empty

Routes object

Key Type Required Default Description
get object true - The configuration for fetching data
- get
route string true - Your data fetching route
sort string true - Your key to sort with
dir string true - Sort by 'asc' or 'desc' order
resultPath object true - The keys object to your data. Required { data: '{your data path in json response. Ex: result.data}'}
params object false - Key-value pairs of additional params that you want to pass to the request

Components object

Components can be defined within this object as key value pairs, where key is the id of the component and needs to be unique and value is a configuration object for the specific component. All available components are listed below with their configuration. Custom components can be added and existing components can be overridden by using the key renderer in the configuration object of the component. Please check the example table config object above.

Layout array

An array of arrays where each inner array represents a row in the layout, within which components can be specified, which will be displayed in the frontend. Please check the example table config object above.

Entity array

All the fields are required when entity is defined (data normalized). However, entity key itself is optional in the table config.

Key Type Required Default Description
state object true - Path to sub state in your top level redux state where the normalized data will be saved
responseSchema object true - Define how the data is represented in your fetch data api response
schema object true - Define how the data is represented in each row item of the table fetch repsonse
selectors object true - Add the selectors that will be used by columns to fetch respective data

Note: Check the example code.

Available Components

Common Properties

Key Type Required Default Description
styles object false {} styled-component styles object or key-value pairs with values being styled-component styles object
renderer function false - returns a react component
type string true - the type of the object
className string true varies html class names for top-level html element in the component
Loader

Note: This component cannot be added to the layout and does not have any other properties except styles.

Styles object properties

Key Type Required Default Description
mask object false {} styled-component styles object
spinner object false {} styled-component styles object
ResultCount

No unique properties

Pages

Properties

Key Type Required Default Description
firstClassName string false rdt-pg-first html class names
lastClassName string false rdt-pg-last html class names
prevClassName string false rdt-pg-prev html class names
nextClassName string false rdt-pg-next html class names
pageNumberClassName string false rdt-pg-num html class names
activeClassName string false active html class names

Styles object properties

Key Type Required Default Description
first object false {} styled-component styles object
last object false {} styled-component styles object
previous object false {} styled-component styles object
next object false {} styled-component styles object
pageNumber object false {} styled-component styles object
Editable (type: editable)

Toggles the table between editable and non-editable and shows a save button when the content of the table is modified

Properties

Key Type Required Default Description
labels object false check below check below
save function false - ( config ) => ( dispatch, getState ) => { ... }
classNames object false check below check below

classNames object properties

Key Type Required Default Description
show string false rdt-toolbar-button html class names
hide string false rdt-toolbar-button html class names
save string false Sardt-toolbar-buttonve html class names

Labels object properties

Key Type Required Default Description
show string false Make editable Label for the button to show editable table
hide string false Hide editable Label for the button to hide editable table
save string false Save Label for the button to save the modified table

Styles object properties

Key Type Required Default Description
show object false {} styled-component styles object
hide object false {} styled-component styles object
save object false {} styled-component styles object
Actions (type: mass-actions)

Properties

Key Type Required Default Description
options array true [] array of actions objects
label string true - Label for the actions dropdown button
btnClassName string false rdt-toolbar-button html class names
menuClassName string false rdt-toolbar-menu html class names
menuItemClassName string false rdt-toolbar-item html class names
activeClassName string false show html class names

Actions object properties

Key Type Required Default Description
type string true - action
name string true - Unique name
label string true - Label for the action item
role string false - Add role 'menu-item' to hide dropdown on click
thunk function true - ( config ) => ( dispatch, getState ) => { ... }

Styles object properties

Key Type Required Default Description
button object false {} styled-component styles object
dropdownMenu object false {} styled-component styles object
dropdownItem object false {} styled-component styles object
Button (type: button)

Properties

Key Type Required Default Description
label string required - Label for the actions dropdown button
ResetFilters (type: reset-filters)

Properties

Key Type Required Default Description
label string required - Label for the actions dropdown button
Print (type: print)

Makes the table printable.

Properties

Key Type Required Default Description
label string required - Label for the actions dropdown button
Columns (type: columns)

Shows the columns toggling dropdown.

Properties

Key Type Required Default Description
label string required - Label for the actions dropdown button
btnClassName string false rdt-toolbar-button html class names
menuClassName string false rdt-toolbar-menu html class names
menuItemClassName string false rdt-toolbar-item html class names
activeClassName string false show html class names

Styles object properties

Key Type Required Default Description
button object false {} styled-component styles object
dropdownMenu object false {} styled-component styles object
dropdownItem object false {} styled-component styles object
Limiter (type: limiter)
Key Type Required Default Description
options array required [] array of limiter counts
default integer required [] default limiter option (should be a value in the options array above)
selectClassName string false rdt-limiter-select html class names
Table (type: table)
Key Type Required Default Description
columns array required [] array of object with column configuration

Columns object properties

Key Type Required Default Description
name string true - Unique name for the column
label string true - Label for the column
sortable boolean false true Whether the column is sortable
filterable boolean false true Whether the column is filterable
editable boolean false false When the table is set to be editable, set whether the respective column is among the editable
visible boolean false true Whether the column is visible on load
type string true string Available types: selection, number, date, string, image, options, actions
width integer true - Width of the column
textAlign string false left Text alignment in the column
renderer function false - Define a custom renderer for column body.
selector string object false - Define a custom selector to pick the value for the column from the state. When string is used, the selector should be defined under entity.selectors
type: actions
items array true - array of item configuration object
- item configuration object
name string true - Unique name for the action
label string true - Label for the action
thunk function true - An action creator which is dispatched on action click. Check demo schema.

Properties specific to column of type 'options'

Key Type Required Default Description
options object true - Defines options for the column. Check below.

options key is an object with a unique key for each value object. The value object consists of a property label used to define the label of the said option. Please check the following example:

options: {
    active: {
        label: 'Active'
    },
    inactive: {
        label: 'Inactive'
    }
    ...
}

Properties specific to column of type 'actions'

Key Type Required Default Description
items array true - array of item configuration object

Properties for a single item of type 'actions'

Key Type Required Default Description
name string true - Unique name for the action
label string true - Label for the action
thunk function true - An action creator which is dispatched on action click. Check the example below.
styles object false {} styled-component styles object

Example:

{
    type: 'action',
    name: 'edit',
    label: 'Edit',
    btnClass: 'btn btn-secondary',
    icon: 'edit',
    thunk: ( payload ) => ( dispatch, getState ) => {
        console.log('edit', payload, getState());
    },
    styles: { ... }
}

Styles object properties

Key Type Required Default Description
table object false {} styled-component styles object
thead object false {} styled-component styles object
tbody object false {} styled-component styles object
filters object false {} styled-component styles object
tr object false {} check below
th object false {} styled-component styles object
td object false {} check below

tr Styles object properties

Key Type Required Default Description
header object false {} styled-component styles object
filters object false {} styled-component styles object
body object false {} styled-component styles object

td Styles object properties

Key Type Required Default Description
filters object false {} styled-component styles object
body object false {} styled-component styles object

License

The MIT License (MIT)