Ag-Grid React Overview
Full working examples of ag-Grid and React can be found in Github, illustrating
(amongst others) Rich Grids, Filtering with React Components Grid and so on.
ag-Grid React Features
Every feature of ag-Grid is available when using the ag-Grid React Component. The React Component wraps the
functionality of ag-Grid, it doesn't duplicate, so there will be no difference between core ag-Grid and
React ag-Grid when it comes to features.
Configuring the ag-Grid React Component
After importing AgGridReact you can then reference the component inside your JSX definitions.
An example of the Grid Component can be seen below:
// Grid Definition
<AgGridReact
// listening for events
onGridReady={this.onGridReady}
// binding to array properties
rowData={this.state.rowData}
// no binding, just providing hard coded strings for the properties
// boolean properties will default to true if provided (ie animateRows => animateRows="true")
rowSelection="multiple"
animateRows
// setting grid wide date component
dateComponentFramework={DateComponent}
// setting default column properties
defaultColDef={{
headerComponentFramework: SortableHeaderComponent,
headerComponentParams: {
menuIcon: 'fa-bars'
}
}}>
// column definitions
<AgGridColumn field="make"></AgGridColumn>
</AgGridReact>>
Configuring the Columns
Columns can be defined in three ways: declaratively (i.e. via markup), via GridOptions or by binding to
columnDefs on the AgGridReact component.
In all cases all column definition properties can be defined to make up a column definition.
Defining columns declaratively:
// column definitions
<AgGridColumn field="make"></AgGridColumn>
<AgGridColumn field="model"></AgGridColumn>
<AgGridColumn field="price"></AgGridColumn>
Defining columns via GridOptions:
// before render/grid initialisation
this.state = {
gridOptions = {
columnDefs: [
{make: "Toyota", model: "Celica", price: 35000},
{make: "Ford", model: "Mondeo", price: 32000},
{make: "Porsche", model: "Boxter", price: 72000}
]
}
}
// in the render method
<AgGridReact gridOptions={this.state.gridOptions}></AgGridReact>
Defining columns by binding to a property:
// before render/grid initialisation
this.state = {
columnDefs: [
{make: "Toyota", model: "Celica", price: 35000},
{make: "Ford", model: "Mondeo", price: 32000},
{make: "Porsche", model: "Boxter", price: 72000}
]
}
// in the render method
<AgGridReact columnDefs={this.state.columnDefs}></AgGridReact>
Column definitions via markup or on GridOptions are one-off definitions. Subsequent updates will not be
reflected on the Grid. Updates using property binding will be reflected on the Grid.
A full working Grid definition is shown below, illustrating various Grid & Column property definitions:
<AgGridReact
// listening for events
onGridReady={this.onGridReady}
// binding to array properties
rowData={this.state.rowData}
// no binding, just providing hard coded strings for the properties
// boolean properties will default to true if provided (ie animateRows => animateRows="true")
rowSelection="multiple"
animateRows
// setting grid wide date component
dateComponentFramework={DateComponent}
// setting default column properties
defaultColDef={{
sortable: true,
filter: true,
headerComponentFramework: SortableHeaderComponent,
headerComponentParams: {
menuIcon: 'fa-bars'
}
}}>
<AgGridColumn headerName="#" width={30} checkboxSelection suppressMenu pinned></AgGridColumn>
<AgGridColumn headerName="Employee" headerGroupComponentFramework={HeaderGroupComponent}>
<AgGridColumn field="name" width={150} pinned editable cellEditorFramework={NameCellEditor}></AgGridColumn>
<AgGridColumn field="country"
width={150}
pinned editable cellRenderer={RichGridDeclarativeExample.countryCellRenderer}
filterParams={{cellRenderer: RichGridDeclarativeExample.countryCellRenderer, cellHeight:20}}></AgGridColumn>
</AgGridColumn>
</AgGridReact>
Loading CSS
You need 1) the core ag-Grid css and 2) a theme. These are stored in css files packaged
in the core ag-Grid. To access them, first up we need to define an alias to use inside
webpack.config.js:
resolve: {
alias: {
"ag-grid-community": path.resolve('./node_modules/ag-grid-community')
Once this is done, we can then access the two css files that we need as follows:
import 'ag-grid-community/dist/styles/ag-grid.css';
import 'ag-grid-community/dist/styles/ag-theme-balham.css';
You will also need to configure CSS loaders for Webpack - you can find a full working example of this in our React Examples Repo on Github.
Applying a Theme
You need to set a theme for the grid. You do this by giving the grid a CSS class, one
of ag-theme-balham, ag-theme-material, ag-theme-fresh, ag-theme-blue or ag-theme-dark. You must have the CSS loaded as specified above
for this to work.
// a parent container of the grid, you could put this on your body tag
// if you only every wanted to use one style of grid
// HTML
<div class="ag-theme-balham">
...
// OR JSX
<div className="ag-theme-balham">
...
// then later, use the grid
<AgGridReact
...
Grid API
When the grid is initialised, it will fire the gridReady event. If you want to
use the API of the grid, you should put an onGridReady(params) callback onto
the grid and grab the api from the params. You can then call this api at a later
stage to interact with the grid (on top of the interaction that can be done by
setting and changing the props).
// provide gridReady callback to the grid
<AgGridReact
onGridReady={this.onGridReady}
.../>
// in onGridReady, store the api for later use
onGridReady = (params) => {
this.api = params.api;
this.columnApi = params.columnApi;
}
// use the api some point later!
somePointLater() {
this.api.selectAll();
this.columnApi.setColumnVisible('country', visible);
}
The api and columnApi are also stored inside the React backing object
of the grid. So you can also look up the backing object via React and access the
api and columnApi that way.
Now would
be a good time to try it in a simple app and get some data displaying and practice with
some of the grid settings before moving onto the advanced features of cellRendering
and custom filtering.
Cell Rendering, Cell Editing and Filtering using
React
It is possible to build cell renderers,
cell editors and
filters using React. Doing each of these
is explained in the section on each.
Override React Components Container Style
When you provide a React Component to ag-Grid for use within the grid it will create a div for the component
to live in. If you wish to override the style of this div you can do so via the reactContainer property
made available via props:
constructor(props) {
super(props);
// change the containing div to be inline-block (instead of the default block for a div)
this.props.reactContainer.style.display = "inline-block";
// change the background color of the containing div to be red
this.props.reactContainer.style.backgroundColor = "red";
}
You can see an example of this in the
Grouped Row Example
where we change the display of the groupRowInnerRendererFramework to inline-block so that the +/- and label are inline.
Performance Pitfalls
If you find that ag-Grid is re-rendering everything and you're not expecting this, then you're probably changing a
property
unexpectedly - below we document some common pitfalls that are easily avoided:
- Binding to methods in the React binding
- Changing references to colDefs (even if the contents are the same)
- Changing references to rowData (even if the contents are the same)
- Processing data before passing it down to ag-Grid
Binding to methods in the React binding
If you have something like:
<AgGridReact
// events
onGridReady={this.onGridReady.bind(this)}>
//... rest of the configuration
Then everytime the component renders, a new instance of onGridReady will be passed to ag-Grid and it will believe
that it's a different function. To avoid this, do the binding separately (in the constructor for example):
class TopMoversGrid extends Component {
constructor(props) {
super(props);
// grid events
this.onGridReady = this.onGridReady.bind(this);
}
render() {
return (
<div className="ag-theme-balham">
<AgGridReact
// events
onGridReady={this.onGridReady}>
//... rest of the component
Now ag-Grid will get the same function everytime the component renders.
Changing references to colDefs (even if the contents are the same)
This happens most commonly when using redux - even if the actual colDefs aren't changing, ag-Grid gets a new reference
to each time there are changes, which causes a change cycle to occur.
To alleviate this extract the colDefs from the changing state (i.e. if the columns aren't likely to change extract them
into a component variable, and pass this to ag-Grid).
Changing references to rowData (even if the contents are the same)
As above, you can either extract this rowData into a separate variable if the data isn't actually changing, or make use of the
enableImmutableMode above.
Processing data before passing it down to ag-Grid
Similar to the items above, processing data and then passing this to ag-Grid, even if the resulting data hasn't changes, can
result is ag-Grid changing state.
A common scenario might be where you pre-process your row data before passing it to ag-Grid - for example:
class TopMoversGrid extends Component {
constructor(props) {
super(props);
}
cleanData = () => {
return this.props.rowData.filter(data => data.isClean)
}
render() {
return (
<AgGridReact
rowData={this.cleanData()}
// ...rest of the component
As above, this call will result in ag-Grid believing that the rowData has changed each time the component renders as the filtering
operation will return a new array each time. Again to alleviate this behaviour extract data that isn't likely to change and pre-process it only once.
React Portals
Within ag-Grid we make use of ReactDOM.unstable_renderSubtreeIntoContainer to dynamically generate React components within the grid.
This has worked well and been reliable since ag-Grid was created, but it is marked as unstable and so could be removed by the React team at any time.
With React 16 Portals were introduced and these are the preferred way to create React components dynamically.
If you wish to try use this feature you'll need to enable it as follows:
// Grid Definition
<AgGridReact
reactNext={true}
...other bindings
React Portals with Redux
One of the downsides of using the React Portal functionality is that there are a few more steps required for the newly
created React components to be Redux aware.
Make the Store Available to ag-Grid
When using React Portals we need to explicity suplly the store to the dynamically created component. In order to
be able to do this you in turn need to supply the store to ag-Grid React via the React context:
// Grid Definition
<AgGridReact
reactNext={true}
reduxStore={this.context.store} // must be supplied when using redux with reactNext
...other bindings
To ensure the store is available on the context you need to add it to the parent component contextTypes:
GridComponent.contextTypes = {
store: PropTypes.object
};
Higher Order Components
If you use connect to use Redux, or if you're using a Higher Order Component to wrap the React component at all,
you'll also need to ensure the grid can get access to the newly created component. To do this you need to ensure withRef
is set:
export default connect(
(state) => {
return {
currencySymbol: state.currencySymbol,
exchangeRate: state.exchangeRate
}
},
null,
null,
{ forwardRef: true } // must be supplied for react/redux when using GridOptions.reactNext
)(PriceRenderer);
React Context API
If you're using the new React Context API then you can access the context in the components used within the grid.
First, let's create a context we can use in our components:
import React from "react";
export default React.createContext('normal');
Next we need to provide the context in a parent component (at the Grid level, or above) - for example:
<FontContext.Provider value="bold">
<GridComponent/>
</FontContext.Provider>
Finally, we need to consume the context within our component:
class StyledRenderer extends Component {
render() {
return (
<FontContext.Consumer>
{fontWeight => <span style={{fontWeight}}>Stylised Component!</span> }
</FontContext.Consumer>
);
}
}
Working Example
You can find a fully working example at our ag Grid React Example.
The Simple Redux Example makes use of reactNext together with Redux.
Test our React Grid component
Next Steps
Now you can go to reference
to learn about accessing all the features of the grid.