Highlighting a FlexGrid Row After the Grid Is Loaded Without Refreshing in React
Background:
When using Wijmo FlexGrid, you may need to highlight a specific row after the grid has already loaded. A common mistake is trying to add a CSS class directly to grid rows, columns, or cells.
That approach does not work because rows[i], columns[i], and cells in the FlexGrid object model are not DOM elements. FlexGrid virtualizes cells, meaning the DOM elements are created, reused, and recycled as needed.
The right approach is to apply styling through FlexGrid’s row or column styling APIs, such as cssClass or cssClassAll, or to use the formatItem event for more customized cell-level styling. After changing the styling property, call invalidate() to repaint the grid. This does not reload the data.
Steps to Complete:
- Install Wijmo packages.
- Import Wijmo styles.
- Create a FlexGrid with sample data.
- Add a CSS class for the highlighted row.
- Apply the CSS class to a row using
cssClassAll. - Repaint the grid using
invalidate(). - Clear the row highlight when needed.
Getting Started:
Install Wijmo packages
Ensure the required Wijmo React packages are available in your project.
npm i @mescius/wijmo @mescius/wijmo.react.grid @mescius/wijmo.styles
@mescius/wijmoincludes the core Wijmo modules.@mescius/wijmo.react.gridincludes the React wrapper forFlexGrid.@mescius/wijmo.stylesincludes the default Wijmo CSS.
Import Wijmo styles
Import the Wijmo CSS file in your React entry file or component file.
import '@mescius/wijmo.styles/wijmo.css';
import './style.css';
Create a FlexGrid with sample data
This creates a basic FlexGrid and binds it to a data array. The grid is configured with manually defined columns and row selection enabled.
const App = () => {
const gridRef = useRef(null);
const [data] = useState(makeSampleData());
const initGrid = (grid) => {
gridRef.current = grid;
};
return (
<main className="page">
<h1>FlexGrid Row Highlight</h1>
<FlexGrid
itemsSource={data}
autoGenerateColumns={false}
selectionMode={wjGrid.SelectionMode.Row}
initialized={initGrid}
>
<FlexGridColumn
binding="varEmployeeID"
header="Employee ID"
width={120}
/>
<FlexGridColumn
binding="employeeName"
header="Name"
width="*"
/>
<FlexGridColumn
binding="department"
header="Department"
width={160}
/>
<FlexGridColumn
binding="hiresThisWeek"
header="Hires"
width={90}
/>
</FlexGrid>
</main>
);
};
function makeSampleData() {
return [
{
varEmployeeID: 1001,
employeeName: 'Avery Johnson',
department: 'Sales',
hiresThisWeek: 2
},
{
varEmployeeID: 1002,
employeeName: 'Blake Kim',
department: 'HR',
hiresThisWeek: 0
},
{
varEmployeeID: 1003,
employeeName: 'Casey Patel',
department: 'Engineering',
hiresThisWeek: 1
},
{
varEmployeeID: 1004,
employeeName: 'Devon Smith',
department: 'Support',
hiresThisWeek: 3
},
{
varEmployeeID: 1005,
employeeName: 'Emerson Lee',
department: 'Marketing',
hiresThisWeek: 0
}
];
}
-
The important part is that the grid rows are Wijmo row objects, not HTML row elements. That is why DOM methods like
addClass()are the wrong tool here.
Add a CSS class for the highlighted row
This defines the styling that will be applied to the row.
.wj-cell.fg-cell-bad,
.wj-header.fg-cell-bad {
background: #d32f2f;
color: #fff;
}
- The selector targets Wijmo grid cells and row headers that receive the
fg-cell-badclass.
Apply the CSS class to a row using cssClassAll
Use cssClassAll when you want the class applied to all cells in the row, including the row header.
const markRowBad = (rowIndex) => {
const grid = gridRef.current;
if (!grid) {
return;
}
if (rowIndex < 0 || rowIndex >= grid.rows.length) {
alert('Row index is out of range.');
return;
}
// Applies to all cells in that row, including row headers.
grid.rows[rowIndex].cssClassAll = 'fg-cell-bad';
// Repaint only. This does not reload the data.
grid.invalidate();
};
- This is the correct replacement for trying to call
addClass()on a row or cell.
Repaint the grid using invalidate()
After assigning cssClassAll, call:
grid.invalidate();
- This tells FlexGrid to repaint itself.
- This is not a data refresh. It does not reload the
itemsSource, recreate the data array, or fetch data again. It only redraws the grid so the new class appears in the rendered cells.
Clear the row highlight when needed
If only one row should be highlighted at a time, clear the existing row classes before marking another row.
const clearRowHighlights = () => {
const grid = gridRef.current;
if (!grid) {
return;
}
for (let i = 0; i < grid.rows.length; i += 1) {
grid.rows[i].cssClassAll = null;
}
grid.invalidate();
};
Then call both methods together:
clearRowHighlights();
markRowBad(0);
- This removes the previous highlight and applies the class to the target row.
Combined Example
import React, { useRef, useState } from 'react';
import { FlexGrid, FlexGridColumn } from '@mescius/wijmo.react.grid';
import * as wjGrid from '@mescius/wijmo.grid';
import '@mescius/wijmo.styles/wijmo.css';
import './style.css';
const App = () => {
const gridRef = useRef(null);
const [data] = useState(makeSampleData());
const [rowIndex, setRowIndex] = useState(0);
const initGrid = (grid) => {
gridRef.current = grid;
};
const markRowByIndex = () => {
const idx = Number(rowIndex);
if (!Number.isFinite(idx)) {
alert('Enter a valid row index.');
return;
}
clearRowHighlights();
markRowBad(idx);
};
const markSelectedRow = () => {
const grid = gridRef.current;
if (!grid || !grid.selection) {
return;
}
const idx = grid.selection.row;
if (idx < 0) {
alert('Select a row first.');
return;
}
clearRowHighlights();
markRowBad(idx);
};
const markRowBad = (rowIndex) => {
const grid = gridRef.current;
if (!grid) {
return;
}
if (rowIndex < 0 || rowIndex >= grid.rows.length) {
alert('Row index is out of range.');
return;
}
// Applies to all cells in that row, including row headers.
grid.rows[rowIndex].cssClassAll = 'fg-cell-bad';
// Repaint only. This does not reload the data.
grid.invalidate();
};
const clearRowHighlights = () => {
const grid = gridRef.current;
if (!grid) {
return;
}
for (let i = 0; i < grid.rows.length; i += 1) {
grid.rows[i].cssClassAll = null;
}
grid.invalidate();
};
return (
<main className="page">
<h1>FlexGrid Row Highlight</h1>
<section className="controls">
<label>
Row index:{' '}
<input
type="number"
value={rowIndex}
min="0"
step="1"
onChange={(e) => setRowIndex(e.target.value)}
/>
</label>
<button type="button" onClick={markRowByIndex}>
Mark row as bad
</button>
<button type="button" onClick={markSelectedRow}>
Mark selected row as bad
</button>
<button type="button" onClick={clearRowHighlights}>
Clear highlight
</button>
</section>
<FlexGrid
itemsSource={data}
autoGenerateColumns={false}
selectionMode={wjGrid.SelectionMode.Row}
initialized={initGrid}
>
<FlexGridColumn
binding="varEmployeeID"
header="Employee ID"
width={120}
/>
<FlexGridColumn
binding="employeeName"
header="Name"
width="*"
/>
<FlexGridColumn
binding="department"
header="Department"
width={160}
/>
<FlexGridColumn
binding="hiresThisWeek"
header="Hires"
width={90}
/>
</FlexGrid>
<p className="hint">
Click a row to select it, then press “Mark selected row as bad”.
</p>
</main>
);
};
function makeSampleData() {
return [
{
varEmployeeID: 1001,
employeeName: 'Avery Johnson',
department: 'Sales',
hiresThisWeek: 2
},
{
varEmployeeID: 1002,
employeeName: 'Blake Kim',
department: 'HR',
hiresThisWeek: 0
},
{
varEmployeeID: 1003,
employeeName: 'Casey Patel',
department: 'Engineering',
hiresThisWeek: 1
},
{
varEmployeeID: 1004,
employeeName: 'Devon Smith',
department: 'Support',
hiresThisWeek: 3
},
{
varEmployeeID: 1005,
employeeName: 'Emerson Lee',
department: 'Marketing',
hiresThisWeek: 0
}
];
}
export default App;
With this React setup:
- A row can be highlighted after the grid has loaded.
- The grid does not need to reload its data.
cssClassAllapplies the CSS class to all cells in the row, including the row header.invalidate()repaints the grid so the class becomes visible.- The highlight can be cleared or moved to another row.
Happy coding!