Griddle makes few assumptions about how your grid should be styled. Griddle grids render as simple tables that you can apply your site's styling to.
Out of the box, Griddle has sorting, filtering, paging and some user customization such as column selection and results per page. Additionally, Griddle supports simple sub-grids and even more complex functionality is on the roadmap.
Griddle is powered by React and its virtual DOM. Only the current page of the grid is rendered at any given time. Whether you have several or hundreds of records, Griddle should render your data quickly.
Griddle is in npm as griddle-react -- simply install react and griddle-react from npm.
npm install react --save
npm install griddle-react --save
From there, require React and Griddle in your modules and you should be all set!
var React = require('react');
var Griddle = require('griddle-react');
Please take a look at a basic gulp example or a webpack example for more information.
At the most basic level, using Griddle is as simple as wiring up an array of JSON objects as a property to the component. First off, include Underscore, React and Bootstrap if you like (bootstrap is not a requirement). Include Griddle and the stylesheet before your React Code.
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet" />
<link href="css/griddle.css" rel="stylesheet" />
...
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js"></script>
<script src="//fb.me/react-0.10.0.js"></script>
<script src="//fb.me/JSXTransformer-0.10.0.js"></script>
<script type="text/javascript" src="scripts/griddle.js"></script>
Define an array of JSON objects -- for our examples we have something that resembles the following:
var fakeData = [
{
"id": 0,
"name": "Mayer Leonard",
"city": "Kapowsin",
"state": "Hawaii",
"country": "United Kingdom",
"company": "Ovolo",
"favoriteNumber": 7
},
...
];
From there, render a Griddle component through React.renderComponent or in the Render method of another component.
<Griddle results={fakeData} tableClassName="table"/>
For many applications, simple paging and sorting is not enough. Griddle comes equipped with filtering, initial columns and additional grid settings out of the box. To use these features, simply define the showProperties and showFilters properties on the Griddle component definition. Check out the full list of properties below.
Using the same data as in the previous example, we can add filtering, grid settings and default columns by defining our component as follows:
<Griddle results={fakeData} tableClassName="table" showFilter={true} showSettings={true} columns={["name", "city", "state", "country"]}/>
Griddle also supports subgrids with little configuration. Simply add a property named "children" (or set the child column name property when defining the component) to any object in your list of data. Right now subgrids only work when the parent and child have the same columns, however, more advanced subgrid functionality is planned.
Don't want to load all of your data at once? Set the 'getExternalData' property to point to a method that accepts the filters and a callback function as parameters and passes the results (along with the total number of results) into the callback.:
var fakeDataMethod = function(filterString, sortColumn, sortAscending, page, pageSize, callback) {
// Load results from your API here.
callback(function() {
results: [],
totalResults: 300
});
}
Then initialize your component with the following:
<Griddle getExternalResults={fakeDataMethod} tableClassName="table"/>
Decide you don't want your grid to look like a grid? We've got you covered. Just set the property 'useCustomFormat' to true and pass in another component as property named 'customFormat'. The component should look a little like this:
var OtherComponent = React.createClass({
getDefaultProps: function(){
return { "data": {} };
},
render: function(){
return ({this.props.data.name});
}
});
}
Please note: the data property is what Griddle will pass the row data in as so be sure to use that on your component.
Then initialize your component as follows:
<Griddle results={fakeData} tableClassName="table" useCustomFormat="true" customFormat={OtherComponent} />
If you want to customize the paging component, just set the property 'useCustomPager' to true and pass in another component as property named 'customPager'. The example component below shows 11 buttons (5 previous, current, 5 next):
var OtherPager = React.createClass({
getDefaultProps: function(){
return{
"maxPage": 0,
"nextText": "",
"previousText": "",
"currentPage": 0,
}
},
pageChange: function(event){
this.props.setPage(parseInt(event.target.getAttribute("data-value")));
},
render: function(){
var previous = "";
var next = "";
if(this.props.currentPage > 0){
previous = <span onClick={this.props.previous} className="previous"><i className="glyphicon glyphicon-arrow-left"></i>{this.props.previousText}</span>
}
if(this.props.currentPage != (this.props.maxPage -1)){
next = <span onClick={this.props.next} className="next">{this.props.nextText}<i className="glyphicon glyphicon-arrow-right"></i></span>
}
var options = [];
var startIndex = Math.max(this.props.currentPage - 5, 0);
var endIndex = Math.min(startIndex + 11, this.props.maxPage);
if (this.props.maxPage >= 11 && (endIndex - startIndex) <= 10) {
startIndex = endIndex - 11;
}
for(var i = startIndex; i < endIndex ; i++){
var selected = this.props.currentPage == i ? "current-page-selected" : "";
options.push(<button className={selected} data-value={i} onClick={this.pageChange}>{i + 1}</button>);
}
return (
<div className="row custom-pager">
<div className="col-xs-4">{previous}</div>
<div className="col-xs-4 center pages">
{options}
</div>
<div className="col-xs-4 right">{next}</div>
</div>
)
}
});
Then initialize your component as follows:
<Griddle results={fakeData} tableClassName="table" useCustomFormat="true" customFormat={OtherComponent} useCustomPager="true" customPager={OtherPager} />
Griddle will, by default, show a message if there is no data in the result set. There are two ways that it can be customized though. You can pass in your own custom message, called noDataMessage.
<Griddle results={fakeData} noDataMessage={"No data could be found."} tableClassName="table"/>
You can also create your own custom component to be rendered when there are no results. Pass it into the customNoData property. The component should look something like this:
var CustomNoDataComponent = React.createClass({
var previous = "";
var next = "";
if(this.props.currentPage > 0){
previous = <span onClick={this.props.previous} className="previous"><i className="glyphicon glyphicon-arrow-left"></i>{this.props.previousText}</span>
}
if(this.props.currentPage != (this.props.maxPage -1)){
next = <span onClick={this.props.next} className="next">{this.props.nextText}<i className="glyphicon glyphicon-arrow-right"></i></span>
}
var options = [];
var startIndex = Math.max(this.props.currentPage - 5, 0);
var endIndex = Math.min(startIndex + 11, this.props.maxPage);
if (this.props.maxPage >= 11 && (endIndex - startIndex) <= 10) {
startIndex = endIndex - 11;
}
for(var i = startIndex; i < endIndex ; i++){
var selected = this.props.currentPage == i ? "current-page-selected" : "";
options.push(<button className={selected} data-value={i} onClick={this.pageChange}>{i + 1}</button>);
}
return (
<div className="row custom-pager">
<div className="col-xs-4">{previous}</div>
<div className="col-xs-4 center pages">
{options}
</div>
<div className="col-xs-4 right">{next}</div>
</div>
)
});
}
Then modify your Griddle statement to pass in the new component.
<Griddle results={fakeData} customNoData={CustomNoDataComponent} tableClassName="table"/>