Skip to main content

Better Way to Make a Shared Data Grid Using Material UI and React


Sometime ago I have a requirement to make a shared data grid that can use inside different components in the react.

I tried with different scenarios but couldn’t figure out a better way to make a shared data grid with different options. My requirement is also gather with Typescript and Material UI version 5.0.

So I used their latest Material data grid free release(version 6). When we plan to use v6 data grid, It is bit different than version 5. So I like to show how I fulfill my requirements and how I made my components in a better way.

Ok let’s go.

First we need to have latest react version and Material UI version up to 5. Then in here I’m planning to work on Material UI x-data-grid version 6.

In here I’m using Typescript to show the coding examples.

Ok, Let’s create our shared data grid components like below. I will explain about some properties I have used inside this data grid Material UI component.

This is my basic setup of data grid component.

import React from 'react';
import { DataGrid, DataGridProps, GridToolbar } from '@mui/x-data-grid';

const PAGE_SIZE = 10;
const PAGE_SIZE_OPTIONS = [10, 15, 30];

interface GridProps extends DataGridProps {
initialStateValue: object,
}

const SharedDataGrid: React.FunctionComponent<GridProps> = (props) => {
return (
<>
<DataGrid
pageSizeOptions={PAGE_SIZE_OPTIONS}
density="standard"
rowHeight={50}
initialState={{
...props.initialStateValue,
pagination: {
paginationModel: { pageSize: PAGE_SIZE, page: 0 }
},
}}
slots={{ toolbar: GridToolbar }}
slotProps={{ toolbar: { csvOptions: {disableToolButton: true }, printOptions: { disableToolButton: true }} }}
disableColumnFilter
disableColumnMenu
paginationMode="server"
{...props}
/>

</>

);
}

export default SharedDataGrid;

Ok, So this is our basic shared component. I have disabled Column filtering and Column menu options with print page option and CSV download options for simplicity. You can enable those things if you need.

In here we use slot props to enable toolbar inside the table header. It includes print page, CSV option etc…

For more details about pagination, you can refer Material UI official documentation page.

Pagination model official documentation.

For use this shared component we can make our main component like below.

import React from 'react';
import { Grid } from '@mui/material';
import { GridColDef } from '@mui/x-data-grid';
import uuid4 from 'uuid4';

import SharedDataGrid from './shared/DataGrid';

const App: React.FunctionComponent = () => {
// define table columns
const tableColumns: GridColDef[] = [
{
field: 'firstName',
headerName: 'First Name',
width: 160,
editable: false,
sortable: false,
},
{
field: 'lastName',
headerName: 'Last Name',
width: 160,
editable: false,
sortable: false,
},
];

// initial data
const dummyData = [
{
"id": uuid4(),
"firstName": "Peter",
"lastName": "John"
},
{
"id": uuid4(),
"firstName": "Will",
"lastName": "Smith",
}
];
return (
<>
<h1>App</h1>
<SharedDataGrid
columns={tableColumns}
rows={dummyData}
getRowId={(row) =>
row.id}
initialStateValue={dummyData}
/>
</>

)
};

export default App;

For now our basic shared data table component and the main component is completed.

In here we defined unique row id as my result array id and also pass initial values as my dummy result array.

Think, sometimes you need to reset the page and the page size. As an example If we need to reset the start page number and the page size when doing a custom search, how can we achieve that.

So for that data grid have a prop called as apiRef.

We can use that prop to change the page size and other related things. This apiRef should be defined inside the data grid component. I just used a trigger value to re-render my component.

import React from 'react';
import { DataGrid, DataGridProps, GridToolbar, useGridApiRef } from '@mui/x-data-grid';

const PAGE_SIZE = 10;
const PAGE_SIZE_OPTIONS = [10, 15, 30];

interface GridProps extends DataGridProps {
initialStateValue: object,
}

const SharedDataGrid: React.FunctionComponent<GridProps> = (props) => {
const apiRef = useGridApiRef();

useEffect(() => {
if(trigger) {
apiRef.current.setPageSize(10);
apiRef.current.setPage(0);
}
}, [trigger, apiRef])

return (
<>
<DataGrid
pageSizeOptions={PAGE_SIZE_OPTIONS}
density="standard"
rowHeight={50}
initialState={{
...props.initialStateValue,
pagination: {
paginationModel: { pageSize: PAGE_SIZE, page: 0 }
},
}}
slots={{ toolbar: GridToolbar }}
slotProps={{ toolbar: { csvOptions: {disableToolButton: true }, printOptions: { disableToolButton: true }} }}
disableColumnFilter
disableColumnMenu
paginationMode="server"
apiRef={apiRef}
{...props}
/>

</>

);
}

export default SharedDataGrid;

For more details about apiRef you can refer their official document page.

You can do much more customization with their data grid pro versions. In this article I used only their free version.

I know this is not looks like a complex part. But I had some issues when I was creating this data grid. So I think this will helpful for someone.

Thank you. Enjoy the content.


Comments

Popular posts from this blog

How to create cloned object using Java

I have an experience with updating a user profile with checking unique email and phone number. In that case I want to get my previous profile details and want to set new updated object details. But after I set the new object details to my retrieved previous object, my previous object setting with new data. So I have a way to again recall the previous data object using a database call.  But if you prefer to maintain a performance based app, you can reduce the database call using cloning the objects. Here actually we create the same object as old and new two objects.  First I will show how we can achieve using Java 8 version. Think if you have two classes Profile and DomainEntity. Here actually DomainEntity used for extend generic objects like created date, updated date etc. @Getter @Setter public class DomainEntity {     private Date createdDate;     private Date updatedDate;     private boolean deleted; } @Getter @Setter public class Profile exten...

Building a Resilient Upsert in Spring Boot

I got this idea when I was working on a project that deals with a third party API. Actually my requirement was to update the database everytime if there is any new change with my third party API. So, it comes like this. I had a project that needed to sync the country list from a third party API. It is very simple as you know and the countries are not going to change in future. It is most likely the same country list. But the issue comes now. Sometimes they remove some countries from their list because they stop supporting that specific country. (Think the API is not providing a webhook). So, now what can I do? Can I use the same country list and throw errors from my system everytime. No, I had to think about a solution to update the country list every time. When I was thinking about a way to update the list, I found a better and efficient way to solve this problem. So, I will explain the steps I followed to solve this issue. Before that you can ask why you can’t keep the country list r...