Building Customizable Dashboard Widgets Using React Grid Layout
We use drag and drop in our interfaces everyday like google keep, gmail, trello etc., It gives more flexibility to the apps for moving data around the application with user interaction. So I came across this feature in one of our clients where they needed draggable and resizable cards/widgets which store the information. As we were building the application using React, I had to look for libraries/packages which support React. This brings us to why React Grid Layout was the choice for this project. So, before I take you into how you can use it to build a customizable dashboard, let’s understand why React.
Why We Used React Grid Layout?
After some digging I found some packages like React DnD and react-draggable which provide drag and drop functionality . But we needed both draggable and also resizable widgets. I found this very handy and helpful package called react-grid-layout which serves both of our requirements. React Grid Layout is helpful when a user wants to build something like a dashboard with draggable and resizable widgets.
Github link : https://github.com/react-grid-layout/react-grid-layout
Unlike other packages it supports breakpoints and it is responsive which helps developers to eliminate writing the extra code for mobile and web platforms. The breakpoints can be auto-generated or given by the user. We can also add or remove the widgets without rebuilding the whole grid layout.
Some of the features of react-grid-layout are :
Pros of React Grid Layout
Creating Customizable Dashboard Widgets
Before diving into the process of building the dashboard with Reach Grid Layout, let me lay down the requirements.
Prerequisites
Implementation
Install the package in your react application :
npm i react-grid-layout
We need to import the Responsive component and WidthProvider HOC from react-grid-layout.
import { Responsive, WidthProvider } from "react-grid-layout"
So to make the layout responsive to screen size , We need to provide the Responsive component as a parameter to the WidthProvider HOC. Then the grid layout will be automatically responsive when the user changes his screen size.
const ResponsiveReactGridLayout = WidthProvider(Responsive)
We need to import default styles of react-grid-layout to make it work as expected. Also we can override the styles of grid layout by mentioning class name to the layout.
import "react-grid-layout/css/styles.css"
import "react-resizable/css/styles.css"
So now we need to render the layout. The layout is an array where we predefine its position. The layout array consists of several objects. Each object will determine the initial position, height, width of the widget which we are rendering. This Object contains mainly five parameters . They are :
We will predefine this layout and keep it in a state called widgetArray.
const [widgetArray, setWidgetArray] = useState([
{ i: "widget1", x: 0, y: 0, w: 2, h: 2 },
{ i: "widget2", x: 2, y: 2, w: 2, h: 2 },
{ i: "widget3", x: 4, y: 4, w: 2, h: 2 },
])
This array can be modified by adding, deleting or changing the position of the objects using the setWidgetArray function.
By rendering the ResponsiveReactGridLayout component inside our component we can check how the layout is rendered inside our application.
<ResponsiveReactGridLayout
onLayoutChange={handleModify}
verticalCompact={true}
layout={layouts}
breakpoints={{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }}
preventCollision={false}
cols={{ lg: 8, md: 8, sm: 4, xs: 2, xxs: 2 }}
autoSize={true}
margin={{
lg: [20, 20],
md: [20, 20],
sm: [20, 20],
xs: [20, 20],
xxs: [20, 20],
}}
>
When using Responsive react grid layout , it is best to supply as many breakpoints as possible, especially the largest one. If the largest is provided, RGL will attempt to interpolate the rest.
React grid layout has several properties where we can modify the widgets however we want. Some of them are :
It is possible to supply default mappings via the data-grid property on individual items, so that they would be taken into account within layout interpolation.
In our case we are supplying the default mappings using the state widgetArray and looping the array in data-grid .
{widgetArray?.map((widget, index) => {
return (
<div
className="reactGridItem"
key={index}
data-grid={{
x: widget?.x,
y: widget?.y,
w: widget?.w,
h: widget?.h,
i: widget.i,
minW: 2,
maxW: Infinity,
minH: 2,
maxH: Infinity,
isDraggable: true,
isResizable: true,
}}
>
Here we can also bound the widget height and width using minH,maxH and minW and maxW. isDraggable and isResizable props can be mentioned in grid-item which helps us in writing the logic for widget view mode and widget edit mode. Also we can add or delete widgets by removing the objects from the widgetArray.
Get the full code here.
There are several use cases for React grid layout. Check them here:
FAQs
1. Why are My Widgets Overlapping?
Incorrect or conflicting layout prop values (x, y, w, h) may cause this. Validate and adjust them.
2. Can I Disable Dragging or Resizing for Specific Widgets?
Yes, React Grid Layout allows you to use the isDraggable and isResizable properties at the widget level. You can set these to false for specific widgets to prevent them from being dragged or resized.
3. How Can I Persist the Widget Layout Across Sessions?
You can use the onLayoutChange property to capture the updated layout whenever widgets are moved or resized. Save the updated layout in your database or local storage and reload it when the dashboard initializes.
4. How Can I Dynamically Add or Remove Widgets?
You can dynamically modify the widgetArray state. To add a widget, append a new object with i, x, y, w, and h properties to the array. To remove a widget, filter the array to exclude the widget with the matching i property.
This article was originally published on our blog. Read the full version here: Building Customizable Dashboard Widgets Using React Grid Layout
Published by: prasad bhat