How to add buttons in material-ui data grid rows? - reactjs

I want to add buttons in each row of the material-ui data grid... But when I'm trying to do so, I see the output as follows (rather than the button it shows something like [object Object].
enter image description here
Below is my code:
import { DataGrid } from "#mui/x-data-grid";
import React, { useState } from "react";
function App() {
const columns = [
{ field: "id", headerName: "ID", width: 70 },
{ field: "firstName", headerName: "First name", width: 130 },
{ field: "lastName", headerName: "Last name", width: 130 },
{
field: "age",
headerName: "Age",
type: "number",
width: 90,
},
{
field: "fullName",
headerName: "Full name",
description: "This column has a value getter and is not sortable.",
sortable: false,
width: 160,
valueGetter: (params) =>
`${params.getValue(params.id, "firstName") || ""} ${
params.getValue(params.id, "lastName") || ""
}`,
},
{
field: "click",
headerName: "Click",
type: <button />, /*this field stores the buttons*/
width: 90,
},
];
const [rows, setRows] = useState([
{
id: 1,
lastName: "Snow",
firstName: "<a>hello</a>",
age: 35,
click: <button>Hello</button>, /*given a button to first row*/
},
{ id: 2, lastName: "Lannister", firstName: "Cersei", age: 42 },
{ id: 3, lastName: "Lannister", firstName: "Jaime", age: 45 },
{ id: 4, lastName: "Stark", firstName: "Arya", age: 16 },
{ id: 5, lastName: "Targaryen", firstName: "Daenerys", age: null },
{ id: 6, lastName: "Melisandre", firstName: null, age: 150 },
{ id: 7, lastName: "Clifford", firstName: "Ferrara", age: 44 },
{ id: 8, lastName: "Frances", firstName: "Rossini", age: 36 },
{ id: 9, lastName: "Roxie", firstName: "Harvey", age: 65 },
]);
// setRows(
// setRows(rows);
// );
const [count, setCount] = useState(0);
const [arr, setArr] = useState([1, 2, 3]);
return (
<>
<p>you pressed {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
<div style={{ height: 400, width: "50%" }}>
<DataGrid
rows={rows}
columns={columns}
pageSize={5}
rowsPerPageOptions={[5]}
checkboxSelection
/>
</div>
<table>
{arr.map((n) => (
<tr>${n}</tr>
))}
</table>
<button
onClick={(e) => {
e.preventDefault();
arr.push(4);
console.log(arr);
var t = [...rows, { id: 3 }];
// rows.push({ lastName: "hello" });
// setRows(t);
setRows(t);
console.log(rows);
// document.title = arr;
setArr(arr);
}}
>
add
</button>
</>
);
}
export default App;
Also, after the button is inserted, how can I reference the current index or id of the row inside the button, suppose if at every click of button I need to show an alert which displays the information such as id and firstname for that row... how can i do that?

use render cell:
{
field: "click",
headerName: "Click",
width: 90,
renderCell: (params) => {
// you will find row info in params
<button>Click</button>
}
},

Related

Is there a way to check a single column's values in MUI Data Grid?

I have a MUI Data Grid with an editable column called 'Status', which can have three values - "Accepted", "Ready for Review" and "Update Required". OnCellCommit, I would like to be able to check if all rows in the Grid have been marked as "Accepted" and enable a button. Is there a way I can achieve this?
hey You can try something like this
import * as React from 'react';
import Box from '#mui/material/Box';
import { DataGrid, GridColDef, GridValueGetterParams } from '#mui/x-data-grid';
const columns: GridColDef[] = [
{ field: 'id', headerName: 'ID', width: 90 },
{
field: 'firstName',
headerName: 'First name',
width: 150,
editable: true,
},
{
field: 'lastName',
headerName: 'Last name',
width: 150,
editable: true,
},
{
field: 'age',
headerName: 'Age',
type: 'number',
width: 110,
editable: true,
},
{
field: 'fullName',
headerName: 'Full name',
description: 'This column has a value getter and is not sortable.',
sortable: false,
width: 160,
valueGetter: (params: GridValueGetterParams) =>
`${params.row.firstName || ''} ${params.row.lastName || ''}`,
},
];
const rows = [
{ id: 1, lastName: 'Snow', firstName: 'Jon', age: 35 },
{ id: 2, lastName: 'Lannister', firstName: 'Cersei', age: 42 },
{ id: 3, lastName: 'Lannister', firstName: 'Jaime', age: 45 },
{ id: 4, lastName: 'Stark', firstName: 'Arya', age: 16 },
{ id: 5, lastName: 'Targaryen', firstName: 'Daenerys', age: null },
{ id: 6, lastName: 'Melisandre', firstName: null, age: 150 },
{ id: 7, lastName: 'Clifford', firstName: 'Ferrara', age: 44 },
{ id: 8, lastName: 'Frances', firstName: 'Rossini', age: 36 },
{ id: 9, lastName: 'Roxie', firstName: 'Harvey', age: 65 },
];
const singleColumn = (c, r) => {
const index = c.filter((ele) => {
console.log(ele.field);
return ele.field == 'age'; //change the age to your desired feild name
});
return r.map((e) => {
const ele = index[0].field;
return e[ele];
});
};
export default function DataGridDemo() {
return (
<Box sx={{ height: 400, width: '100%' }}>
<DataGrid
rows={rows}
columns={columns}
pageSize={5}
rowsPerPageOptions={[5]}
checkboxSelection
disableSelectionOnClick
experimentalFeatures={{ newEditingApi: true }}
>
{console.log('gg', singleColumn(columns, rows))}
</DataGrid>
</Box>
);
}

Material UI Datagrid not displaying Edit and Delete buttons in a row React js

I cannot be able to render the custom code for Edit and Delete in a row data.I am using MUI datatables passing columns and rows.But, for rows data is showing fine but for edit and delete [object object] is showing up instead of rendering the component.
Below is the code
In the map function I am adding the edit and delete code bu it is showing me like [object object] instead of the component. Here I am adding the edit and delete to display in the row with Icons.
import { Button, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, IconButton, Paper } from '#material-ui/core';
import React, { useState } from 'react';
import DeleteOutlineIcon from "#material-ui/icons/DeleteOutline";
import EditIcon from "#material-ui/icons/Edit";
import { DataGrid } from "#material-ui/data-grid";
export const DataTable = () => {
const columns = [
{ field: 'id', headerName: '# ID', width: 70, disableColumnMenu: true, disableColumnFilter: true, disableColumnSelector: true, sortable: false },
{ field: 'name', headerName: 'Name', width: 130, disableColumnMenu: true, disableColumnFilter: true, disableColumnSelector: true, sortable: false },
{ field: 'edit', headerName: ' ', width: 130 , disableColumnMenu: true, disableColumnFilter: true, disableColumnSelector: true, sortable: false },
{ field: 'delete', headerName: ' ', width: 130, disableColumnMenu: true, disableColumnFilter: true, disableColumnSelector: true, sortable: false }
];
const rows = [
{ id: 1, name: 'Snow', firstName: 'Jon', age: 35 },
{ id: 2, name: 'Lannister', firstName: 'Cersei', age: 42 },
{ id: 3, name: 'Lannister', firstName: 'Jaime', age: 45 },
{ id: 4, name: 'Stark', firstName: 'Arya', age: 16 },
{ id: 5, name: 'Targaryen', firstName: 'Daenerys', age: null },
{ id: 6, name: 'Melisandre', firstName: null, age: 150 },
{ id: 7, name: 'Clifford', firstName: 'Ferrara', age: 44 },
{ id: 8, name: 'Frances', firstName: 'Rossini', age: 36 },
{ id: 9, name: 'Roxie', firstName: 'Harvey', age: 65 },
];
const bodyData = rows.map( ( row, index ) => {
return {
...row,
"edit": (<IconButton
style={{ padding: "8px" }}
onClick={(e) => {
e.stopPropagation();
alert("test")
}}
id={`a_${row.id}`}
>
<EditIcon style={{ fontSize: "16px" }} />
</IconButton>),
"delete": (<IconButton
style={{ padding: "8px" }}
onClick={(e) => {
e.stopPropagation();
alert("test")
}}
id={`b_${row.id}`}
>
<DeleteOutlineIcon style={{ fontSize: "20px" }} />
</IconButton>)
}});
return (
<div style={{ height: 400, width: '100%' }}>
<DataGrid
rows={bodyData}
columns={columns}
pageSize={5}
rowsPerPageOptions={[5]}
/>
</div>
);
}
This is not the right way to do it, look at the documentation
It's the columns that must manage the UI and not the rows
const headers = columns.map( ( col ) => {
return {
field: col.field,
headerName: col.headerName,
width: col.width || "200",
renderCell: cellRenderer,
sortable: false,
};
});
const cellRenderer = (params) => {
return params.value;
};
Use renderCell and rendering the custom components

How do i place this DataGrid in Material Ui correctly?

I have tried a lot of different solutions to make this grid perfectly fit in, i can not seem to understand material ui sizing within this space.
As you can see the column titles are missing, and it's not centered in the middle.
I have used the clipped drawer also from MUI which is placed inside of Box
import * as React from "react";
import { DataGrid } from "#mui/x-data-grid";
import { Container, Grid, Paper, Box } from "#mui/material";
const columns = [
{ field: "id", headerName: "ID", width: 90 },
{
field: "firstName",
headerName: "First name",
width: 150,
editable: true,
},
{
field: "lastName",
headerName: "Last name",
width: 150,
editable: true,
},
{
field: "age",
headerName: "Age",
type: "number",
width: 110,
editable: true,
},
{
field: "fullName",
headerName: "Full name",
description: "This column has a value getter and is not sortable.",
sortable: false,
width: 160,
valueGetter: (params) =>
`${params.row.firstName || ""} ${params.row.lastName || ""}`,
},
];
const rows = [
{ id: 1, lastName: "Snow", firstName: "Jon", age: 35 },
{ id: 2, lastName: "Lannister", firstName: "Cersei", age: 42 },
{ id: 3, lastName: "Lannister", firstName: "Jaime", age: 45 },
{ id: 4, lastName: "Stark", firstName: "Arya", age: 16 },
{ id: 5, lastName: "Targaryen", firstName: "Daenerys", age: null },
{ id: 6, lastName: "Melisandre", firstName: null, age: 150 },
{ id: 7, lastName: "Clifford", firstName: "Ferrara", age: 44 },
{ id: 8, lastName: "Frances", firstName: "Rossini", age: 36 },
{ id: 9, lastName: "Roxie", firstName: "Harvey", age: 65 },
];
export default function DataGridDemo() {
return (
<Container>
<Paper component={Box} width={1} height={700}>
<DataGrid
rows={rows}
columns={columns}
pageSize={5}
rowsPerPageOptions={[5]}
checkboxSelection
disableSelectionOnClick
/>
</Paper>
</Container>
);
}
You need to add <Toolbar/>
import Toolbar from '#mui/material/Toolbar';
<Container>
<Toolbar/>
<Paper component={Box} width={1} height={700}>
<DataGrid
rows={rows}
columns={columns}
pageSize={5}
rowsPerPageOptions={[5]}
checkboxSelection
disableSelectionOnClick
/>
</Paper>
</Container>```
Put your code on codesandbox.io so that It easy to figure out the problem

Get the selected values in a datagrid with material ui

I have a datagrid with several elements and I would like to retrieve the checked datas.
I saw in the element document that there is a controlled selection but I can't get it to work.
I'll put my current code below, thanks in advance!
import * as React from 'react';
import { DataGrid } from '#material-ui/data-grid';
const columns = [
{ field: 'id', headerName: 'ID', width: 70 },
{ field: 'firstName', headerName: 'First name', width: 130 },
{ field: 'lastName', headerName: 'Last name', width: 130 },
{
field: 'age',
headerName: 'Age',
type: 'number',
width: 90,
},
{
field: 'fullName',
headerName: 'Full name',
description: 'This column has a value getter and is not sortable.',
sortable: false,
width: 160,
valueGetter: (params) =>
`${params.getValue('firstName') || ''} ${
params.getValue('lastName') || ''
}`,
},
];
const rows = [
{ id: 1, lastName: 'Snow', firstName: 'Jon', age: 35 },
{ id: 2, lastName: 'Lannister', firstName: 'Cersei', age: 42 },
{ id: 3, lastName: 'Lannister', firstName: 'Jaime', age: 45 },
{ id: 4, lastName: 'Stark', firstName: 'Arya', age: 16 },
{ id: 5, lastName: 'Targaryen', firstName: 'Daenerys', age: null },
{ id: 6, lastName: 'Melisandre', firstName: null, age: 150 },
{ id: 7, lastName: 'Clifford', firstName: 'Ferrara', age: 44 },
{ id: 8, lastName: 'Frances', firstName: 'Rossini', age: 36 },
{ id: 9, lastName: 'Roxie', firstName: 'Harvey', age: 65 },
];
export default function App() {
const [select, setSelection] = React.useState([]);
return (
<div style={{ height: 400, width: '100%' }}>
<DataGrid
rows={rows}
columns={columns}
pageSize={25}
checkboxSelection
hideFooterPagination
onSelectionChange={(newSelection) => {
setSelection(newSelection.rows);
}}
/>
<h1>{select}</h1>
</div>
);
}
If you log your select state you can see that the state is being set according to what is selected. onSelectionChange callback newSelection parameter already contains what you seek.
The main issue with your code is <h1>{select}</h1>. While select is indeed an array and arrays are valid React children, each of your array element contains an object (e.g., firstName, lastName), therefore it won't work with that setup.
You may iterate over the array and print each individual array element object property value.
Example below is printing out firstName:
return (
<div style={{ height: 400, width: "100%" }}>
<h1>{select.map((val) => val.firstName)}</h1>
<DataGrid
rows={rows}
columns={columns}
pageSize={25}
checkboxSelection
hideFooterPagination
onSelectionChange={(newSelection) => {
setSelection(newSelection.rows);
}}
/>
</div>
);
The documentation was updated, and I updated this example: answer from this topic, now according to the documentation selectionModel contains an array of id selected rows
I believe you could start by getting total rows onRowSelected, or from the context on some other event method by stepping into the api a bit. This is as of 03/2020, but I found nothing on this in the API docs:
onRowSelected={(x) => x.api.current.getSelectedRows()}, on DataGrid "#material-ui/data-grid": "^4.0.0-alpha.22" works for me. I can do everything I need from this in my case.
<div style={{ height: 400, width: "100%" }}>
<h1>{select.map((val) => val.firstName)}</h1>
<DataGrid
rows={rows}
columns={columns}
pageSize={25}
checkboxSelection
hideFooterPagination
onSelectionChange={(newSelection) => {
setSelection(newSelection.rows);
}}
/>
</div>
);
<https://mui.com/components/data-grid/selection/#heading-controlled-selection>
Summarisation of the ans from #95faf8e76605e973 and comment from #abderrezague mohamed for anyone want to copy and paste
return (
<div style={{ height: 400, width: "100%" }}>
<h1>{select.map((val) => val.firstName)}</h1>
<DataGrid
rows={rows}
columns={columns}
pageSize={25}
checkboxSelection
hideFooterPagination
onSelectionModelChange={(newSelectionArray) => {
// newSelectionArray is [5,1] given the select order is 5 then 1
}}
/>
</div>
);

Can I initialize the checkbox selection in MUI DataGrid?

In a MUI DataGrid it is super easy to add a checkbox selection via the checkboxSelection attribute and listen to selection changes via onSelectionChange:
<DataGrid
columns={columns}
rows={rows}
pageSize={10}
checkboxSelection
onSelectionChange={e => console.log(e.rows)}
/>
But is there also a way to initialize the checkbox selection with a set of checked items?
Currently the DataGrid doesn't have a way to set the default selectionModel (something like defaultSelectionModel prop), so in order to set the default selected rows, you need to use controlled mode by adding selectionModel/onSelectionModelChange and pass the initial value in useState. It's an ID array of the rows you wish to select at the start.
const rows = [
{ id: 1, lastName: "Snow", firstName: "Jon", age: 35 },
{ id: 2, lastName: "Lannister", firstName: "Cersei", age: 42 },
{ id: 3, lastName: "Lannister", firstName: "Jaime", age: 45 },
{ id: 4, lastName: "Stark", firstName: "Arya", age: 16 },
{ id: 5, lastName: "Targaryen", firstName: "Daenerys", age: null },
{ id: 6, lastName: "Melisandre", firstName: null, age: 150 },
{ id: 7, lastName: "Clifford", firstName: "Ferrara", age: 44 },
{ id: 8, lastName: "Frances", firstName: "Rossini", age: 36 },
{ id: 9, lastName: "Roxie", firstName: "Harvey", age: 65 }
];
function MyDataGrid() {
const [selectionModel, setSelectionModel] = React.useState(() =>
rows.filter((r) => r.age > 40).map((r) => r.id),
);
return (
<div style={{ height: 400, width: '100%' }}>
<DataGrid
checkboxSelection
rows={rows}
columns={columns}
selectionModel={selectionModel}
onSelectionModelChange={setSelectionModel}
/>
</div>
);
}
Live Demo
The DataGrid has a selectionModel property that accepts an array of row IDs.
<DataGrid
columns={columns}
rows={rows}
pageSize={10}
checkboxSelection
onSelectionChange={e => console.log(e.rows)}
selectionModel={[rowId1, rowId2, rowId3]}
/>
import * as React from "react";
import {
DataGrid,
RowData,
useRows,
useApiRef,
GridApi,
} from "#material-ui/data-grid";
import { useDemoData } from "#material-ui/x-grid-data-generator";
let i = 0;
export default function ControlledSelectionGrid() {
const apiRef = React.useRef(null);
console.log("apiRef:", apiRef);
const ObjRef = React.useRef({
dataRe:{
columns:[],
rows:[]
}
})
const counterRef = React.useRef({
renderCount:0
})
// TODO: https://github.com/mui-org/material-ui-x/issues/246
const [selection, setSelection] = React.useState([]);
const columns = [
{ field: "id", headerName: "ID", width: 70 },
{ field: "firstName", headerName: "First name", width: 130 },
{ field: "lastName", headerName: "Last name", width: 130 },
{
field: "age",
headerName: "Age",
type: "number",
width: 90,
},
{
field: "fullName",
headerName: "Full name",
description: "This column has a value getter and is not sortable.",
sortable: false,
width: 160,
valueGetter: (params) =>
`${params.getValue("firstName") || ""} ${
params.getValue("lastName") || ""
}`,
},
];
const rows = [
{ id: 1, lastName: "Snow", firstName: "Jon", age: 35 },
{ id: 2, lastName: "Lannister", firstName: "Cersei", age: 42 },
{ id: 3, lastName: "Lannister", firstName: "Jaime", age: 45 },
{ id: 4, lastName: "Stark", firstName: "Arya", age: 16 },
{ id: 5, lastName: "Targaryen", firstName: "Daenerys", age: null },
{ id: 6, lastName: "Melisandre", firstName: null, age: 150 },
{ id: 7, lastName: "Clifford", firstName: "Ferrara", age: 44 },
{ id: 8, lastName: "Frances", firstName: "Rossini", age: 36 },
{ id: 9, lastName: "Roxie", firstName: "Harvey", age: 65 },
];
//console.log('dataRe out:',ObjRef.current.dataRe)
React.useEffect(() => {
const dataRe = {
columns,
rows
}
ObjRef.current.dataRe = dataRe
counterRef.current.renderCount +=1
console.log('no of render**:',counterRef.current.renderCount)
console.log('apiRef.current**:',apiRef.current)
//console.log('in useEffect..')
const rowModels = apiRef?.current?.getRowModels();
console.log("rowModels:", rowModels);
console.log('dataRe',dataRe)
if (rowModels!=undefined) {
if(apiRef.current){
apiRef.current.setRowModels(
rowModels.map((r) => {
//console.log("rowModel row:", r);
r.selected = r.data.age > 40;
return r;
})
);
}
}
},[apiRef.current]);
return (
<div style={{ height: 400, width: "100%" }}>
<DataGrid
checkboxSelection
onSelectionChange={(newSelection) => {
setSelection(newSelection.rows);
}}
components={{
noRowsOverlay: (params) => {
//console.log('params in noRowsOverlay:',params)
if (!apiRef.current) {
//console.log('in apiRef current noRowsOverlay')
apiRef.current = params.api.current;
//console.log('apiRef.current in noRowOverlay:',apiRef.current)
}
return <div>No rows</div>;
},
}}
{...ObjRef.current.dataRe}
/>
</div>
);
}

Resources