Adding colDefs dynamically - reactjs

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/

Related

How to map my firestore collection documents into a table

So I have a collection in firebase and want all the documents populated in the table dynamically. At the moment, it just populates the last document onto the table even after using the spread operator. Somebody help me with a solution to this. Thank you.
Here is the code:
import React, { useEffect, useState } from "react";
import { collection, getDocs } from "firebase/firestore";
import { db } from "../../firebase/firebase";
import { DataGrid } from "#mui/x-data-grid";
const columns = [
{ field: "name", headerName: "Name", width: 160 },
{ field: "email", headerName: "Email", width: 210 },
{ field: "roles", headerName: "Roles", width: 160 },
{ field: "isSuspended", headerName: "Suspended", width: 130 },
{ field: "lastUpdated", headerName: "Last Updated", width: 150 },
{ field: "updatedByEmail", headerName: "Updated By", width: 150 },
];
export default function Admins() {
const [row, setRow] = useState([]);
useEffect(() => {
const getAdmins = async () => {
const admins = await getDocs(collection(db, "admins"));
admins.forEach((admin) => {
console.log(admin.data());
setRow([
...row,
{
id: admin.data().email,
name: admin.data().name,
email: admin.data().email,
roles: admin.data().roles,
isSuspended: admin.data().isSuspended,
lastUpdated: admin.data().lastUpdated,
updatedByEmail: admin.data().updatedByEmail,
},
]);
});
};
getAdmins();
}, []);
console.log("row", row);
return (
<div style={{ height: 400, width: "100%" }}>
<DataGrid
rows={row}
columns={columns}
pageSize={10}
rowsPerPageOptions={[10]}
checkboxSelection
/>
</div>
);
}
The reason this is happening is because the state doesn't update completely until the use effect is done. This means the state is the same as it was before the use effect ran. Here's how you can fix this:
Instead of using
setRow([
...row,
{
id: admin.data().email,
name: admin.data().name,
email: admin.data().email,
roles: admin.data().roles,
isSuspended: admin.data().isSuspended,
lastUpdated: admin.data().lastUpdated,
updatedByEmail: admin.data().updatedByEmail,
},
]);
Use
setRow((r) => ([
...r,
{
id: admin.data().email,
name: admin.data().name,
email: admin.data().email,
roles: admin.data().roles,
isSuspended: admin.data().isSuspended,
lastUpdated: admin.data().lastUpdated,
updatedByEmail: admin.data().updatedByEmail,
},
]));
By passing a function with the r argument, react knows to pass the actual current state value to the function, which will just return something, and that will be put into state.

getRowId from Material UI datagrid doesn't work

I keep getting this error Uncaught Error: MUI: The data grid component requires all rows to have a unique id property. Even though I have passed the getRowId prop into the datagrid and defined what the Id should be. I am fetching this data from a firestore. What might I be doing wrong? Here is the component code:
import React, { useEffect, useState } from "react";
import { collection, getDocs } from "firebase/firestore";
import { db } from "../../firebase/firebase";
import { DataGrid } from "#mui/x-data-grid";
const columns = [
{ field: "name", headerName: "Name", width: 160 },
{ field: "email", headerName: "Email", width: 210 },
{ field: "roles", headerName: "Roles", width: 160 },
{ field: "isSuspended", headerName: "Suspended", width: 130 },
{ field: "lastUpdated", headerName: "Last Updated", width: 150 },
{ field: "updatedByEmail", headerName: "Updated By", width: 150 },
];
export default function Admins() {
const [rows, setRows] = useState([]);
useEffect(() => {
const getAdmins = async () => {
const admins = await getDocs(collection(db, "admins"));
admins.forEach((admin) => {
setRows((row) => [
...row,
{
id: admin.data().email,
name: admin.data().name,
email: admin.data().email,
roles: admin.data().roles,
isSuspended: admin.data().isSuspended,
lastUpdated: admin.data().lastUpdated,
updatedByEmail: admin.data().updatedByEmail,
},
]);
});
};
getAdmins();
}, []);
console.log("rows", rows);
return (
<div style={{ height: "100vh", width: "100%" }}>
<DataGrid
rows={rows}
columns={columns}
getRowId={(row) => row.email}
pageSize={10}
rowsPerPageOptions={[10]}
checkboxSelection
/>
</div>
);
}
One suggestion is to first check if you are getting the value for the row.email in case is returned as undefined and try using optional chaining getRowId={(row) => row?.email}

Ant table custom filter checkbox without dropdown

I am using ant table for my project where I want to filter records on click of checkbox inside my header row, when I click on check box all zero valued rows should be filtered and others should stay, is there any way I can do this?
Demo
You can achieve the desired feature by defining a custom columns title prop that renders a controlled Checkbox component in addition to the column's title string. When the Checkbox is true, you then filter out the table data based on your desired filter condition.
(As an aside, I did initially try to get the same functionality to work via the onFilter and filterIcon approach, but that approach proved unsuccessful.)
import React, { useState } from "react";
import ReactDOM from "react-dom";
import { Table, Checkbox } from "antd";
import "./index.scss";
const DifferenceTable = (props) => {
const [isChecked, setIsChecked] = useState(false);
const data = [
{
date: "2020-06-17",
units: 2353.0,
amount: 8891206.27,
date: 2323,
units: 243234,
amount: 234234,
units_diff: 0,
amount_diff: 0
},
{
date: "2020-06-17",
units: 2353.0,
amount: 8891206.27,
date: 2323,
units: 243234,
amount: 234234,
units_diff: 1,
amount_diff: 1
}
];
const processedData = isChecked
? data.filter((datum) => datum.units_diff || datum.amount_diff)
: data;
const columns = [
{
title: "Bank",
children: [
{
title: "Trxn Date",
dataIndex: "date",
key: "date",
width: 100
},
{
title: "Sum Units",
dataIndex: "units",
key: "units",
width: 100
},
{
title: "Sum Amounts",
dataIndex: "amount",
key: "units",
width: 100
}
]
},
{
title: "CUSTOMER",
children: [
{
title: "Trxn Date",
dataIndex: "date",
key: "date",
width: 100
},
{
title: "Sum Units",
dataIndex: "units",
key: "units",
width: 100
},
{
title: "Sum Amounts",
dataIndex: "amount",
key: "amount",
width: 100
}
]
},
{
title: () => (
<div>
<span>Difference </span>
<Checkbox
checked={isChecked}
onChange={(e) => {
setIsChecked(e.target.checked);
}}
/>
</div>
),
dataIndex: "units_diff",
key: "units_diff",
children: [
{
title: "Units",
dataIndex: "units_diff",
key: "units_diff",
width: 100
},
{
title: "Amounts",
dataIndex: "amount_diff",
key: "amount_diff",
width: 100
}
],
align: "center"
}
];
return (
<Table
// rowKey="uid"
className="table diff_table"
columns={columns}
dataSource={processedData}
pagination={false}
scroll={{ y: 400, x: 0 }}
/>
);
};
ReactDOM.render(<DifferenceTable />, document.getElementById("container"));
A functional demo is available at the following CodeSandbox link

What am I doing wrong with the ag-grid in react?

I'm trying to make the the ag-grid group selectable if say for example we have the care maker and you can select the parent and everything underneath that parent also gets selected.
I've looked into the ag-grid documentation but it looks like I'm doing everything right.
Here's my code below:
import React, { useState } from 'react';
import { AgGridReact, AgGridColumn } from 'ag-grid-react';
import 'ag-grid-community/dist/styles/ag-grid.css';
import 'ag-grid-community/dist/styles/ag-theme-balham.css';
const DummyGrid = () => {
const [gridApi, setGridApi] = useState(null);
const columnDefs = [
{
headerName: 'Make', field: 'make', checkboxSelection: true , rowGroup: true, groupSelectsChildren: true
},
{
headerName: 'Model', field: 'model'
},
{
headerName: 'Price', field: 'price'
}
]
const onGridReady = (params) => {
setGridApi(params.api);
}
const rowData = [
{ make: 'Honda', model: 'Chev', price: 6000 },
{ make: 'Honda', model: 'Civic', price: 120000 },
{ make: 'Toyota', model: 'Celica', price: 5000 },
{ make: 'Mitsubishi', model: 'GTR', price: 5000 }
]
const handleClick = () => {
const selectedNodes = gridApi.getSelectedNodes();
const selectedData = selectedNodes.map(node => node.data);
const selectedDataStringRepresentation = selectedData.map(node => node.make + ' ' + node.model).join(', ');
console.log(`The Data selected: ${selectedDataStringRepresentation}`);
}
return(
<div className="ag-theme-balham"
style={{
width: 600,
height: 600
}}>
<button onClick={handleClick}>Click this!</button>
<AgGridReact
rowData = {rowData}
columnDefs={columnDefs}
rowSelection="multiple"
onGridReady={onGridReady}
/>
</div>
);
};
export default DummyGrid;
As you can see from the output below that they're not grouping even though they the same maker. What am I doing wrong?
2 things you're doing wrong.
First, you need to import the RowGroupingModule module and pass it to your grid as modules:
import { RowGroupingModule } from '#ag-grid-enterprise/row-grouping';
modules={[RowGroupingModule]}
Secondly, you need to set groupSelectsChildren on the grid itself, not on your column definition:
groupSelectsChildren={true}
Demo.

React Data Grid shows bad

I have a problem with ReactDataGrid component. I have already installed react-data-grid. The code is the same as in the reac grid's web:
const columns = [
{ key: 'id', name: 'ID' },
{ key: 'title', name: 'Title' },
{ key: 'count', name: 'Count' }];
const rows = [{ id: 0, title: 'row1', count: 20 }, { id: 1, title: 'row1', count: 40 }, { id: 2, title: 'row1', count: 60 }];
class App extends React.Component {
render() {
return (
<ReactDataGrid
columns={columns}
rowGetter={i => rows[i]}
rowsCount={3}
minHeight={150} />
)
}
}
export default App;
and i get:
Result
Thank you!
Import the CSS like so :
import 'react-data-grid/dist/react-data-grid.css';
It should be fine.
import React from "react";
import ReactDOM from "react-dom";
import ReactDataGrid from "react-data-grid";
const columns = [
{ key: "id", name: "ID", editable: true },
{ key: "title", name: "Title", editable: true },
{ key: "count", name: "Count", editable: true }
];
const rows = [
{ id: 0, title: "row1", count: 20 },
{ id: 1, title: "row1", count: 40 },
{ id: 2, title: "row1", count: 60 }
];
class App extends React.Component {
render() {
return (
<ReactDataGrid
columns={columns}
rowGetter={i => rows[i]}
rowsCount={3}
minHeight={150}
enableCellSelect={true}
/>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
https://codesandbox.io/s/rdg-cell-editing-h8bnr
the answer is in the above code this above code is working
You don't really need to downgrade. The issue is that the css is not being imported.
If you can import css from node-modules, it'll work.
Workaround for me was I took the whole css and we are now self-maintaining the css, making changes when needed.
I couldn't load the css either, I got around this by including
import ReactDataGrid from 'react-data-grid/dist/react-data-grid.min.js';
instead of
import ReactDataGrid from 'react-data-grid';

Resources