How to wrap ag-grid-react into component? - reactjs

I'm using React with Redux. I have a table which is made with ag-grid for react.
Table data can be edited in line and saved.
How to create wrapper component for that table? I need to have multiple tables with same functionality just with different data.
In ag-grid documentation it shows how to implement with redux store and reducers, but this solution only works with one table, because we have only one state per app. I don't want to dublicate my code just because i have two different lists of data...

Here's a quick example
// Grid.jsx
import React, {
PureComponent,
} from 'react';
import {
AgGridReact,
} from 'ag-grid-react';
class Grid extends PureComponent {
state = {
columnDefs : [],
rowData : []
};
/**
* This will set your internal columnDefs & rowData
* from the props being passed in
* <Grid columnDefs={columnDefs} rowData={rowData} />
*/
static getDerivedStateFromProps(nextProps) {
const {
columnDefs,
rowData,
} = nextProps;
return {
columnDefs,
rowData,
};
}
render() {
const {
columnDefs,
rowData,
} = this.state;
return (
<AgGridReact
columnDefs={columnDefs}
rowData={rowData}
/>
);
}
}
export default Grid;
// ExampleImpl.jsx
import Grid from './Grid';
class ExampleImpl extends PureComponent {
render() {
// Assuming you got these from the connect
const rowData: [
{
name: "Ireland",
continent: "Europe",
language: "English",
code: "ie",
population: 4000000,
summary: "Master Drinkers"
},
];
const columnDefs: [
{
headerName: "Name",
field: "name",
cellRenderer: countryCellRenderer
},
{
headerName: "Continent",
field: "continent",
width: 150
},
{
headerName: "Language",
field: "language",
width: 150
}
];
return <Grid
rowData = {rowData}
columnDefs = {columnDefs}
/>
}
}
export default connect(ExampleImpl);
// ExampleImplII.jsx
import Grid from './Grid';
class ExampleImplII extends PureComponent {
render() {
// Assuming you got these from connect
const rowData: [
{
name: "Ireland",
continent: "Europe",
language: "English",
code: "ie",
population: 4000000,
summary: "Master Drinkers"
},
];
const columnDefs: [
{
headerName: "Name",
field: "name",
cellRenderer: countryCellRenderer
},
{
headerName: "Continent",
field: "continent",
width: 150
},
{
headerName: "Language",
field: "language",
width: 150
}
];
return <Grid
rowData={rowData}
columnDefs={columnDefs}
/>
}
}
export default connect(ExampleImplII);
This way you have 1 presentational component and 2 container components (smart components) which know how to fetch the data and just pass it to your presentational component.

Related

Ag-grid slow render after upgrade to v27

I recently upgraded my ag-grid v21 to 27. I'm using node 14.19 and Material-UI v4. When I set my pagination to 30 (it's ok with 10) I have a lag (~0.5sec) and when I go to the next page or if I sort my column and if I add more row to display in my pagination, e.g 100 I'll get more lag (~1sec). With ag-grid v21 I never had this lag I don't understand what I have to change to be ok with ag-grid v27. I just have 500 row in my json object. Here is my code :
import React, { Component } from "react";
import { axiosApiBackend } from "variables/axiosConfigs.jsx";
import PropTypes from "prop-types";
import { AgGridReact } from "ag-grid-react";
import "ag-grid-community/dist/styles/ag-grid.css";
import "ag-grid-community/dist/styles/ag-theme-material.css";
// core components
import GridContainer from "components/Grid/GridContainer.jsx";
import GridItem from "components/Grid/GridItem.jsx";
class Customer extends Component {
constructor(props) {
super(props);
this.BACKEND_URL = "/customers";
this.gridApi = null;
this.gridColumnApi = null;
this.state = {
columnDefs: [
{
headerName: "#",
field: "id",
sort: "desc",
},
{
headerName: "User",
field: "user",
valueGetter: (params) =>
(params.data.lastname || "") + " " + (params.data.firstname || ""),
},
{
headerName: "Email",
field: "email",
},
{
headerName: "Address",
field: "address",
},
{
headerName: "Zip code",
field: "city.zip",
},
{
headerName: "city",
field: "city.name",
},
],
defaultColDef: {
sortable: true,
},
data: null,
frameworkComponents: {},
};
}
componentDidMount() {
this.loadAsyncData();
}
loadAsyncData() {
axiosApiBackend.get(this.BACKEND_URL).then((result) => {
this.setState({ data: result.data }, () => {});
});
}
onGridReady = (params) => {
this.gridApi = params.api;
this.gridColumnApi = params.columnApi;
};
render() {
return (
<GridContainer>
<GridItem xs={12} className="ag-theme-material">
<AgGridReact
domLayout="autoHeight"
rowData={this.state.data}
columnDefs={this.state.columnDefs}
suppressRowClickSelection={true}
groupSelectsChildren={true}
rowSelection={"multiple"}
rowGroupPanelShow={"always"}
pivotPanelShow={"always"}
enableRangeSelection={true}
pagination={true}
paginationPageSize={30}
onGridReady={this.onGridReady}
/>
</GridItem>
</GridContainer>
);
}
}
Customer.propTypes = {
location: PropTypes.any,
history: PropTypes.any,
classes: PropTypes.any,
};
export default Customer;
How can I do to fix this lag ?
Edit:
I just tried the version 26 and I don't have the lag. When I retry the version 27 I got the lag again. I don't know if this bug is related to the v27 or if I have to do something else
Edit 2:
I think the problem is related to https://www.ag-grid.com/react-data-grid/reactui/
So I tried to use the suppressReactUi=true It's a little bit better but the render with v26 is faster. So I don't know why I got the lag with the new render in the v27. Maybe I have to upgrade my react version ?
Try to turn off the React Developer Tools extension
And React in Production Mode works faster than Dev Mode

Adding colDefs dynamically

I'm trying to add the column definition programmatically,on button click, instead of hardcoding it in my ReactJS page.
{
headerName: "Product1",
resizable: true,
wrapText: true,
cellStyle: {
'white-space': 'normal'
},
autoHeight: true,
hide: true,
cellRendererFramework.MyCustomColumnRenderer
}
Not sure how to go about implementing this?
Thanks for your help.
Use setColumnDefs(columnDefs)
const columnDefs = getColumnDefs();
columnDefs.forEach(function (colDef, index) {
colDef.headerName = 'Abcd';
});
this.gridApi.setColumnDefs(columnDefs);
https://plnkr.co/edit/0ctig4P2yzPjhycB
You could define the columnDefs in the grid to use a state and then set the state dynamically.
import React from 'react';
import { render } from 'react-dom';
import { AgGridColumn, AgGridReact } from 'ag-grid-react';
import 'ag-grid-community/dist/styles/ag-grid.css';
import 'ag-grid-community/dist/styles/ag-theme-alpine.css';
const App = () => {
const rowData = [
{ make: 'Toyota', model: 'Celica', price: 35000 },
{ make: 'Ford', model: 'Mondeo', price: 32000 },
{ make: 'Porsche', model: 'Boxter', price: 72000 },
];
// use the colDefs state to define the column definitions
const [colDefs, setColDefs] = React.useState([{ field: 'make' }]);
// when the button is pressed set the state to cause the grid to update
const handleAddColumns = ()=> {
const dynamicFields = [
{ field: 'make', header: 'Car Make' },
{ field: 'model', sortable: true },
{ field: 'price' },
];
setColDefs(dynamicFields);
}
return (
<div>
<button onClick={handleAddColumns}>Add Column Defs</button>
<div className="ag-theme-alpine" style={{ height: 400, width: 600 }}>
<AgGridReact
rowData={rowData}
columnDefs={colDefs}>
</AgGridReact>
</div>
</div>
);
};
render(<App />, document.getElementById('root'));
Another approach is to use the Api's setColumnDef method:
import React from 'react';
import { render } from 'react-dom';
import { AgGridColumn, AgGridReact } from 'ag-grid-react';
import 'ag-grid-community/dist/styles/ag-grid.css';
import 'ag-grid-community/dist/styles/ag-theme-alpine.css';
const App = () => {
const rowData = [
{ make: 'Toyota', model: 'Celica', price: 35000 },
{ make: 'Ford', model: 'Mondeo', price: 32000 },
{ make: 'Porsche', model: 'Boxter', price: 72000 },
];
// using state to define the columns initially
const [colDefs, setColDefs] = React.useState([{ field: 'make' }]);
// get a reference to the API when the onGridReady is fired
// see the Grid definition in the JSX
const [gridApi, setGridApi] = React.useState([]);
const handleAddColumns = ()=> {
const dynamicFields = [
{ field: 'make', header: 'Car Make' },
{ field: 'model', sortable: true },
{ field: 'price' },
];
// use the API to set the Column Defs
gridApi.setColumnDefs(dynamicFields);
}
return (
<div>
<button onClick={handleAddColumns}>Add Column Defs</button>
<div className="ag-theme-alpine" style={{ height: 400, width: 600 }}>
<AgGridReact
rowData={rowData}
columnDefs={colDefs}
onGridReady={ params => {setGridApi(params.api)} }
></AgGridReact>
</div>
</div>
);
};
render(<App />, document.getElementById('root'));
The examples in the documentation should help:
https://www.ag-grid.com/react-data-grid/column-definitions/
https://www.ag-grid.com/react-data-grid/column-updating-definitions/
There is also a blog post from AG Grid that covers dynamic column definitions:
https://blog.ag-grid.com/binding-and-updating-column-definitions-in-ag-grid/

trying to implement a text filter to a ag-grid in a react component

I can't figure out how to implement a simple search bar to the ag-grid i set. I would like to let my input filter the results in my grid based on every columns I couldn't figure out a good documentation with example for that. Here is my code. Feel free to redirect me to a proper example or another question similar.
import React from 'react';
import { AgGridReact } from 'ag-grid-react';
import axios from 'axios';
import 'ag-grid-community/dist/styles/ag-grid.css';
import 'ag-grid-community/dist/styles/ag-theme-alpine.css';
class ListTableClients extends React.Component {
constructor(props) {
super(props);
this.state = {
defaultColDef: {
flex: 1,
cellClass: 'cell-wrap-text',
autoHeight: true,
sortable: true,
resizable: true,
},
columnDefs: [
{ headerName: "id", field: "id", maxWidth: 100 },
{ headerName: "name", field: "name"},
{ headerName: "email", field: "email"}],
rowData: [
{ id: 1, name: 'maison du café', email: 'maisonducafe#gamil.com' },
{ id: 2, name: 'Warehouse', email: 'contact#warehouse.fr' },
{ id: 3, name: 'Maestro', email: 'maestro#gmail.com' }],
rowHeight: 275,
}
}
componentDidMount() {
console.log('test');
axios.get('http://localhost:8080/listClients').then((res) => {
this.setState({ rowData: res.data });
}).catch((error) => { console.log(error) });
}
render() {
return (
<div style={{width: '100%', paddingLeft: '50px', paddingRight: '50px', paddingTop: '50px'}} className="ag-theme-alpine">
<input type="text" placeholder="Filter..." onInput={this.onFilterTextBoxChanged}/>
<AgGridReact
domLayout='autoHeight'
columnDefs={this.state.columnDefs}
defaultColDef={this.state.defaultColDef}
getRowHeight={this.state.getRowHeight}
rowData={this.state.rowData}>
</AgGridReact>
</div>
);
}
}
export default ListTableClients;
Refer this demo
If the cell data in object format then you have to format it Ag-Grid Value Formatters

Setting columnTypes in ag-grid

I'm trying to figure out how to get ag-grid working with Typescript React. I'm trying to make a table with a custom column type. The custom column type and the default column type I'm defining don't seem to be working and I'm not sure why. Here's a simple version of my code:
import React from 'react';
import './App.css';
import { AgGridReact } from 'ag-grid-react';
import { GridOptions } from "ag-grid-community";
import 'ag-grid-community/dist/styles/ag-grid.css';
import 'ag-grid-community/dist/styles/ag-theme-balham.css';
class App extends React.Component<{}, GridOptions> {
constructor(props: GridOptions) {
super(props);
this.state = {
rowData: [
{foo: 1, bar: 'abc'},
{foo: 2, bar: 'def'},
],
columnDefs: [
{headerName: "foo", field: "foo", type: "numberColumn"},
{headerName: "bar", field: "bar"},
],
defaultColDef: {
width: 150,
editable: true,
sortable: true,
filter: "agTextColumnFilter"
},
columnTypes: {
"numberColumn": {
width: 20,
filter: "agNumberColumnFilter"
},
},
onCellClicked: function(event) {window.alert('a row was clicked '+ event.data)},
}
}
render() {
return (
<div
className="ag-theme-balham"
style={{
height: '1000px',
width: '6000px' }}
>
<AgGridReact
columnDefs={this.state.columnDefs}
rowData={this.state.rowData}>
</AgGridReact>
</div>
);
}
}
export default App;
I also found that onCellClicked isn't actually doing anything, so I think I'm misunderstanding something there.
You are defining in your local state but you are not passing it to AgGridReact component this it has no knowledge of it.
You can destructure state properties like below:
const {columnDefs, rowData, defaultColDef, onCellClicked, columnTypes} = this.state
And then use it and pass it like below:
<AgGridReact
columnDefs={columnDefs}
rowData={rowData}
defaultColDef={defaultColDef}
onCellClicked={onCellClicked}
columnTypes={columnTypes}
>
</AgGridReact>

devextreame use in reactjs

I want to use data grid devextreme in react.
I have tried this code but when i run my project i have this error : jQuery is not defined.
when i try to import jquery i still have the error.
import React, {Component} from 'react';
import dxDataGrid from '../../node_modules/devextreme/dist/js/dx.all';
class Grid extends Component {
constructor() {
super();
this.state = {
dataSource: employees,
sorting: {
mode: "multiple"
},
columns: [
{
dataField: "Prefix",
caption: "Title",
width: 70
}, {
dataField: "FirstName",
sortOrder: "asc"
}, {
dataField: "LastName",
sortOrder: "asc"
}, "City",
"State", {
dataField: "Position",
width: 130
}, {
dataField: "HireDate",
dataType: "date"
}
]
}
}
render () {
return (
<div>
<Grid value= "false" text= "Disable Sorting for the Position Column"/>
</div>
)
}
}
export default Grid;

Resources