tablefiniti
v2.0.9
Published
A react component to display information on a react js based table
Downloads
5
Readme
Tablefiniti
Tablefiniti is a table (ReactJS Component) that is adapted for the spefic needs of Datafiniti Web projects that use tables and require a variety of graphicial options, such as expandable rows, custom React Components on divisions and a form-agnostic paradigm.
Initial set up
The initial set up of Tablefiniti is quite easy. First import Tablefiniti into your React Project:
/* Dependency imports */
import React, { Component } from 'react'
import Tablefiniti from 'tablefiniti'
After that the component itself only need 3 obligatory props to work:
rows
an array of rows in the Tablefiniti formatheaders
a simple array of stringstotalRecords
an integer, most of the time returned by the server, that states the total amount of records that can be fetched
A simple set up of the table looks like this:
/* Dependency imports */
import React, { Component } from 'react'
import Tablefiniti from 'tablefiniti'
class SimpleTable extends Component {
render () {
let headers = ['Id', 'Firstname', 'Lastname']
let rows = [{
Id: '1',
Firstname: 'Francisco',
Lastname: 'Jimenez'
}, {
Id: '2',
Firstname: 'Vincent',
Lastname: 'Zierigen'
}]
return (
<Tablefiniti
rows={rows}
headers={headers}
totalRecords={rows.length}
/>
)
}
}
export default SimpleTable
Notice that for totalRecords the length of the
rows
is being used, but most of the time will be a number higher than the amount of the present data, as it can represent the total amount of records a query inside the server holds
Data format and types
The data that Tablefiniti consumes must be in a specific format. Let's take a look at following data:
let headers = ['Id', 'Firstname', 'Lastname']
let rows = [{
Id: '1',
Firstname: 'Juan',
Lastname: 'Valdez'
}, {
Id: '2',
Firstname: 'Jane',
Lastname: 'Doe'
}]
Notice that the keys
on each object that represent a row, match exactly the name of a header
. Tablefiniti will not render a column that does not have matching header. (Credits to: Trevor Pace for the idea of using objects to represent the rows).
So far, only strings are represented on data, but tablefiniti support various types of data. Take a look a this more complex data model:
let headers = ['Id', 'Firstname', 'Lastname', 'Link']
let rows = [{
Id: '1',
Firstname: 'Juan',
Lastname: 'Valdez',
Link: {
type: 'link',
data: 'Go!',
url: '#here'
}
}, {
Id: '2',
Firstname: 'Jane',
Lastname: {
type: 'string',
data: 'Doe'
},
Link: {
type: 'link',
data: 'Download!',
url: '#download'
}
}]
Link is a type of data that generates an <a>
tag with a text inside, being the data
the text and the url the href
used address.
Data Types
There are 3 types of data available for Tablefiniti:
String
Strings can be declared in the complex form using type and data, but it is not necesary, as strings can be interpreted by Tablefiniti in ther simple regular JS form.
Lastname: {
type: 'string',
data: 'Doe'
}
OR
Lastname: 'Doe'
Link
Link: {
type: 'link',
data: 'Download!',
url: 'https://myawesomedomain.com/tablefinitirules:1337'
}
Compound
Compound is a group of 2 text represented as simple strings that can be displayed using the following format:
{
type: 'compound',
title: 'Some Title',
subTitle: `This is a subtitle`
}
Custom
Custom is the most complex of the 3 types as it allows you to create a custom React generator
that returns a React Component.
Sample of a generator function
const editButton = myID => {
return (
<a onClick={alert(myID)} className='btn btn-info btn-sm'>
<span className='icon-pencil' />
</a>
)
}
let rows = [
...
{
'ID': '248148',
'Status': {
type: 'custom',
generator: editButton('Some Text or ID')
},
'Num of Records': '300',
'Date/TimeStarted': 'May 4, 2016 at 3:15pm'
}
...
]
Hidden Rows
Tablefiniti allows you set up hidden rows that are toggable by clicking the first division of the parent
object.
Row with a child element
...
{
'ID': '248148',
'Num of Records': '300',
'Date/TimeStarted': 'May 4, 2016 at 3:15pm',
'Status': 'In Progress',
child: {
title: 'Criteria Selected',
data: {
'Source': '*walmart*',
'SourceUrls': 'Reviews',
'DateUpdated': '*2017-01-30*',
'Brand': 'dell'
}
}
}
...
The data keys of the child object are rendered inside of a single divison ( td
) with a colSpan equal to the amount of columns in the table.
IMPORTANT
The father object's first column corresponding value HAS to be a string for this feature to work correctly, otherwise, Tablefiniti won't process the data and will dispatch an error.
Props
Besides the 3 needed props for operation, Tablefiniti has 2 other props that can be used:
currentPage
currentPage
lets the user ser manually which page should the paginator indicate the table is in. It must be a Number
. This is an optional prop.
sorting
sorting
lets the user override or manually place a sorting object, which should always be in the following format:
sorting: {
header: '', // Must be a valid Table header
order: '' // asc or desc
}
This is an optional prop.
onQueryChange(query)
onQueryChange(query)
is a function prop that can be passed to Tablefiniti, this function will be triggered everytime a part of Tablefiniti regarding the order of view (sorting, paging or records per page) is changed.
Example
...
//Method on the component that holds Tablefiniti
onQueryChange (query) {
//Do something with the query information
}
...
<Tablefiniti onQueryChange={this.onQueryChange} config={config} rows={rows} headers={headers} totalRecords={totalRecords} />
//Example of a complete query object sent from the callback
//Order can be `asc` or `desc`
query {
"currentPage": 4,
"rowsPerPage": 10,
"sorting": {
"header": "Type",
"order": "asc"
}
}
config {}
The config
prop allows the user set up several configuration options to make Tablefiniti more suitable to the user's needs.
Sample of a complete configuration object
let config = {
noDataMessage: 'There is no data available.',
rowsPerPageVisibility: {
up: true,
down: false,
expandCollapse: false
},
customCSS: {
table: 'separation anxiety',
rows: 'spiderman venom mary jane watson',
paginator: 'maximum carnage'
},
nonSortableHeaders: ['Edit'],
childSorting: (propA, propB) => {
if (propA === 'Rank') {
return -1
} else {
return 1
}
}
}
Example (taken from MDN):
function compare(a, b) {
if (a is less than b by some ordering criterion) {
return -1;
}
if (a is greater than b by the ordering criterion) {
return 1;
}
// a must be equal to b
return 0;
}
Note:
rowsPerPageVisibility
allows the user to hide therowsPerPage
on the paginator modules and includes a option calledexpandCollapse
that allows aexpand/collapse
button to appear, this button will either expand of collapse all availble childen row (if any, if there's no children rows, nothing will happen)
This is Tablefiniti's default config inner JSON
{
rowsPerPageVisibility: {
up: true,
down: true,
expandCollapse: false// Option that displays the expand/collapse controller
// it overrides the rowsPerPageVisibility if present
},
customCSS: {
table: '',
rows: '',
paginator: ''
},
nonSortableHeaders: [],
childSorting: null // Function that replaces Array.sort()
} // Config object, taken from props
No data provided
When Tablefiniti recives no data or the data was not fetched, Tablefiniti will display the message inside noDataMessage
on the configuration object. It will render a simple table with the provided headers and the message.
If no headers are provided, then Id and Name will appear as default headers.
Examples
Simple Table
This is a simple example of how to set up Tablefiniti with the bare minimum using the 3 data types:
// Simple example
/* Dependency imports */
import React, { Component } from 'react'
import Tablefiniti from '../Tablefiniti.jsx'
class SimpleTable extends Component {
constructor (props) {
super(props)
this.state = {
rows: [],
headers: []
}
this.editButtonGenerator = this.editButtonGenerator.bind(this)
}
componentDidMount () {
let headers = ['ID', 'Num of Records', 'Date/TimeStarted', 'Status']
let rows = [
{
'ID': '248148',
'Num of Records': '300',
'Date/TimeStarted': 'May 4, 2016 at 3:15pm',
'Status': 'In Progress',
child: {
title: 'Criteria Selected',
data: {
'Source': '*walmart*',
'SourceUrls': 'Reviews',
'DateUpdated': '*2017-01-30*',
'Brand': 'dell'
}
}
},
{
'ID': '248148',
'Status': {
type: 'link',
data: 'Download Records',
url: '#downloads_records'
},
'Num of Records': '300',
'Date/TimeStarted': 'May 4, 2016 at 3:15pm'
},
{
'ID': '248148',
'Status': {
type: 'custom',
generator: this.editButtonGenerator('Hey hey')
},
'Num of Records': '300',
'Date/TimeStarted': 'May 4, 2016 at 3:15pm'
}
]
this.setState({rows, headers})
}
editButtonGenerator (id) {
return (
<a onClick={e => alert(`This would edit id: ${id}`)} className='btn btn-info btn-sm'>
<span className='icon-pencil' />
</a>
)
}
render () {
let { rows, headers } = this.state
if (rows.length === 0 || headers === 0) {
return (<div />)
}
return (
<div style={{margin: 100}}>
<Tablefiniti
rows={rows}
headers={headers}
totalRecords={rows.length}
/>
</div>
)
}
}
export default SimpleTable
Explicit Example
An explicit example that implements all Tablefiniti's options, server simulation and a search form can be seeing here.