Setting columnTypes in ag-grid - reactjs

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>

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

Create a prop for a chart.js pie chart

I'm using Chart.js inside my react project.
and i want to structure my project as neatly as possible by creating components
and calling them on my App.js
How can I go about creating a react prop and calling it from another component without Actually calling my pie chart from the App.js
import React from 'react';
import {Pie} from 'react-chartjs-2';
const state = {
labels: ['January', 'February', 'March',
'April', 'May'],
datasets: [
{
label: 'Rainfall',
backgroundColor: [
'#B21F00',
'#C9DE00',
'#2FDE00',
'#00A6B4',
'#6800B4'
],
hoverBackgroundColor: [
'#501800',
'#4B5000',
'#175000',
'#003350',
'#35014F'
],
data: [65, 59, 80, 81, 56]
}
]
}
export default class App extends React.Component {
render() {
return (
<div>
<Pie
data={state}
options={{
title:{
display:true,
text:'Average Rainfall per month',
fontSize:20
},
legend:{
display:true,
position:'left',
}
}}
/>
</div>
);
}
}
If you create a component named PieChart in the PieChart.js file like this:
import React from 'react';
import { Pie } from 'react-chartjs-2';
export default class PieChart extends React.Component {
render() {
return (
<div>
<Pie
data={this.props.data}
options={{
title: {
display: true,
text: 'Average Rainfall per month',
fontSize: 20
},
legend: {
display: true,
position: 'left',
}
}}
/>
</div>
);
}
}
Then you can import it from the App.js in this way:
import React from 'react';
import PieChart from './PieChart';
const state = {
labels: ['January', 'February', 'March',
'April', 'May'],
datasets: [
{
label: 'Rainfall',
backgroundColor: [
'#B21F00',
'#C9DE00',
'#2FDE00',
'#00A6B4',
'#6800B4'
],
hoverBackgroundColor: [
'#501800',
'#4B5000',
'#175000',
'#003350',
'#35014F'
],
data: [65, 59, 80, 81, 56]
}
]
}
export default class App extends React.Component {
render() {
return (
<PieChart data={state} />
)
}
}
Here I've created a custom props named data and passed it to the PieChart component which is being accessed by this.props.data in the PieChart component. You can create multiple props as you want. Like you can pass options as well in this way.
Also you can keep your data(which is passed from the App as data props) in the PieChart component and call it from anywhere you want by <PieChart />.
Note: I've kept App.js and PieChart.js both files in the same directory.
This how I used piechart in my project:
in another file, you can create a custom component and add your code like below
export const StatusChart = ({ data }) => {
const [pieData, setPieData] = useState({});
useEffect(() => {
setPieData({
labels: ['declined', 'accepted', 'goterror', 'inprogress'],
datasets: [
{
data: [data.inprogress, data.got_error, data.accepted, data.declined],
backgroundColor: ['#F7464A', '#46BFBD', '#FDB45C', '#949FB1', '#4D5360'],
hoverBackgroundColor: ['#FF5A5E', '#5AD3D1', '#FFC870', '#A8B3C5', '#616774'],
},
],
});
}, [data]);
return (
<MDBContainer>
<Pie data={pieData} options={{ responsive: true }} />
</MDBContainer>
);
};
and in App.js you can use useState to save data like below:
const [generalData, setGeneralData] = useState(null);
and use it in your code:
{generalData ? <StatusChart data={generalData.status_chart} /> : <Spinner animation="border" />}

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

Highstocks not showing stock tools

I am trying to plot a time-series but I am not getting the stock tools as in the left-side of this chart. Example from the highstocks website: enter link description here
The code with options:
import React from 'react';
import Highcharts from 'highcharts/highstock'
import HighchartsReact from 'highcharts-react-official'
class Graph extends React.Component {
getOptions = (dataSets) => {
return {
yAxis: [{
labels: {
align: 'left'
},
height: '80%',
resize: {
enabled: true
}
}, {
labels: {
align: 'left'
},
top: '80%',
height: '20%',
offset: 0
}],
title: {
text: 'Summary'
},
series: [{
name: 'INFY',
data: dataSets.data
}]
};
};
render() {
const {dataSets} = this.props;
const options = this.getOptions(dataSets);
return (
<div>
<HighchartsReact
highcharts={Highcharts}
constructorType={'stockChart'}
options={options}
/>
</div>
)
}
}
export default Graph;
Here is what is rendered:
What is going wrong?
EDIT:
After applying the suggestions by #ppotaczek. I get this:
Updated code:
import React from 'react';
import Highcharts from "highcharts/highstock";
import indicatorsAll from "highcharts/indicators/indicators-all";
import annotationsAdvanced from "highcharts/modules/annotations-advanced";
import priceIndicator from "highcharts/modules/price-indicator";
import fullScreen from "highcharts/modules/full-screen";
import stockTools from "highcharts/modules/stock-tools";
import HighchartsReact from "highcharts-react-official";
indicatorsAll(Highcharts);
annotationsAdvanced(Highcharts);
priceIndicator(Highcharts);
fullScreen(Highcharts);
stockTools(Highcharts);
class Graph extends React.Component {
getOptions = (dataSets) => {
return {
yAxis: [{
labels: {
align: 'left'
},
height: '80%',
resize: {
enabled: true
}
}, {
labels: {
align: 'left'
},
top: '80%',
height: '20%',
offset: 0
}],
title: {
text: 'Summary'
},
series: [{
name: 'INFY',
data: dataSets.data
}]
};
};
render() {
const {dataSets} = this.props;
const options = this.getOptions(dataSets);
return (
<div>
<HighchartsReact
highcharts={Highcharts}
constructorType={'stockChart'}
options={options}
/>
</div>
)
}
}
export default Graph;
You need load CSS styles and import and initialize all of the required modules:
import indicatorsAll from "highcharts/indicators/indicators-all";
import annotationsAdvanced from "highcharts/modules/annotations-advanced";
import priceIndicator from "highcharts/modules/price-indicator";
import fullScreen from "highcharts/modules/full-screen";
import stockTools from "highcharts/modules/stock-tools";
indicatorsAll(Highcharts);
annotationsAdvanced(Highcharts);
priceIndicator(Highcharts);
fullScreen(Highcharts);
stockTools(Highcharts);
Live demo: https://codesandbox.io/s/highcharts-react-demo-3s8v7
Docs: https://www.highcharts.com/docs/stock/stock-tools

How to wrap ag-grid-react into component?

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.

Resources