React Hierarchical Grid Sorting
The Ignite UI for React Data Sorting feature in React Hierarchical Grid is enabled on a per-column level, meaning that the IgrHierarchicalGrid
can have a mix of sortable and non-sortable columns. Performing React sort actions enables you to change the display order of the records based on specified criteria.
React Hierarchical Grid Sorting Overview Example
Additionally there is a custom contextmenu added for sorting using IgrHierarchicalGrid
's ContextMenu
Output.
import React from 'react' ;
import ReactDOM from 'react-dom/client' ;
import './index.css' ;
import { IgrHierarchicalGridModule } from "@infragistics/igniteui-react-grids" ;
import { IgrHierarchicalGrid, IgrSortingExpression, SortingDirection, IgrColumn, IgrRowIsland } from "@infragistics/igniteui-react-grids" ;
import SingersData from './SingersData.json' ;
import "@infragistics/igniteui-react-grids/grids/combined" ;
import "@infragistics/igniteui-react-grids/grids/themes/light/bootstrap.css" ;
const mods : any [] = [
IgrHierarchicalGridModule
];
mods.forEach((m) => m.register());
export default class Sample extends React.Component <any, any> {
private hierarchicalGrid1: IgrHierarchicalGrid
private hierarchicalGrid1Ref(r: IgrHierarchicalGrid) {
this .hierarchicalGrid1 = r;
this .setState({});
}
private _sortingExpression1: IgrSortingExpression[] | null = null ;
public get sortingExpression1(): IgrSortingExpression[] {
if (this ._sortingExpression1 == null )
{
let sortingExpression1 : IgrSortingExpression [] = [];
var sortingExpression2: IgrSortingExpression = {} as IgrSortingExpression;
sortingExpression2.fieldName = "Artist" ;
sortingExpression2.dir = SortingDirection.Asc;
sortingExpression2.ignoreCase = true ;
sortingExpression1.push(sortingExpression2)
this ._sortingExpression1 = sortingExpression1;
}
return this ._sortingExpression1;
}
constructor (props: any ) {
super (props);
this .hierarchicalGrid1Ref = this .hierarchicalGrid1Ref.bind(this );
}
public render (): JSX .Element {
return (
<div className ="container sample ig-typography" >
<div className ="container fill" >
<IgrHierarchicalGrid
autoGenerate ="false"
data ={this.singersData}
primaryKey ="ID"
sortingExpressions ={this.sortingExpression1}
ref ={this.hierarchicalGrid1Ref} >
<IgrColumn
field ="Artist"
header ="Artist"
dataType ="String"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="Photo"
header ="Photo"
dataType ="Image" >
</IgrColumn >
<IgrColumn
field ="Debut"
header ="Debut"
dataType ="Number"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="GrammyNominations"
header ="Grammy Nominations"
dataType ="Number"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="GrammyAwards"
header ="Grammy Awards"
dataType ="Number"
sortable ="true" >
</IgrColumn >
<IgrRowIsland
childDataKey ="Albums"
autoGenerate ="false" >
<IgrColumn
field ="Album"
header ="Album"
dataType ="String"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="LaunchDate"
header ="Launch Date"
dataType ="Date"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="BillboardReview"
header ="Billboard Review"
dataType ="String"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="USBillboard200"
header ="US Billboard 200"
dataType ="String"
sortable ="true" >
</IgrColumn >
<IgrRowIsland
childDataKey ="Songs"
autoGenerate ="false" >
<IgrColumn
field ="Number"
header ="No."
dataType ="String"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="Title"
header ="Title"
dataType ="String"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="Released"
header ="Released"
dataType ="Date"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="Genre"
header ="Genre"
dataType ="String"
sortable ="true" >
</IgrColumn >
</IgrRowIsland >
</IgrRowIsland >
<IgrRowIsland
childDataKey ="Tours"
autoGenerate ="false" >
<IgrColumn
field ="Tour"
header ="Tour"
dataType ="String"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="StartedOn"
header ="Started on"
dataType ="String"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="Location"
header ="Location"
dataType ="String"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="Headliner"
header ="Headliner"
dataType ="String"
sortable ="true" >
</IgrColumn >
</IgrRowIsland >
</IgrHierarchicalGrid >
</div >
</div >
);
}
private _singersData: any [] = SingersData;
public get singersData(): any [] {
return this ._singersData;
}
}
const root = ReactDOM.createRoot (document.getElementById('root' ));
root.render (<Sample /> );
tsx コピー
Like this sample? Get access to our complete Ignite UI for React toolkit and start building your own apps in minutes. Download it for free.
This is done via the sortable
input. With the IgrHierarchicalGrid
sorting, you can also set the sortingIgnoreCase
property to perform case sensitive sorting:
<IgrColumn field ="ProductName" header ="Product Name" dataType ="string" sortable ="true" > </IgrColumn >
tsx
Sorting Indicators
Having a certain amount of sorted columns could be really confusing if there is no indication of the sorted order.
The IgrHierarchicalGrid
provides a solution for this problem by indicating the index of each sorted column.
import React from 'react' ;
import ReactDOM from 'react-dom/client' ;
import './index.css' ;
import { IgrHierarchicalGridModule } from "@infragistics/igniteui-react-grids" ;
import { IgrHierarchicalGrid, IgrSortingExpression, SortingDirection, IgrColumn, IgrRowIsland } from "@infragistics/igniteui-react-grids" ;
import SingersData from './SingersData.json' ;
import "@infragistics/igniteui-react-grids/grids/combined" ;
import "@infragistics/igniteui-react-grids/grids/themes/light/bootstrap.css" ;
const mods : any [] = [
IgrHierarchicalGridModule
];
mods.forEach((m) => m.register());
export default class Sample extends React.Component <any, any> {
private hierarchicalGrid1: IgrHierarchicalGrid
private hierarchicalGrid1Ref(r: IgrHierarchicalGrid) {
this .hierarchicalGrid1 = r;
this .setState({});
}
private _sortingExpression1: IgrSortingExpression[] | null = null ;
public get sortingExpression1(): IgrSortingExpression[] {
if (this ._sortingExpression1 == null )
{
let sortingExpression1 : IgrSortingExpression [] = [];
var sortingExpression2: IgrSortingExpression = {} as IgrSortingExpression;
sortingExpression2.dir = SortingDirection.Asc;
sortingExpression2.fieldName = "Artist" ;
sortingExpression2.ignoreCase = true ;
sortingExpression1.push(sortingExpression2)
var sortingExpression3: IgrSortingExpression = {} as IgrSortingExpression;
sortingExpression3.dir = SortingDirection.Desc;
sortingExpression3.fieldName = "Debut" ;
sortingExpression3.ignoreCase = true ;
sortingExpression1.push(sortingExpression3)
var sortingExpression4: IgrSortingExpression = {} as IgrSortingExpression;
sortingExpression4.dir = SortingDirection.Asc;
sortingExpression4.fieldName = "GrammyNominations" ;
sortingExpression4.ignoreCase = true ;
sortingExpression1.push(sortingExpression4)
var sortingExpression5: IgrSortingExpression = {} as IgrSortingExpression;
sortingExpression5.dir = SortingDirection.Asc;
sortingExpression5.fieldName = "GrammyAwards" ;
sortingExpression5.ignoreCase = true ;
sortingExpression1.push(sortingExpression5)
this ._sortingExpression1 = sortingExpression1;
}
return this ._sortingExpression1;
}
constructor (props: any ) {
super (props);
this .hierarchicalGrid1Ref = this .hierarchicalGrid1Ref.bind(this );
}
public render (): JSX .Element {
return (
<div className ="container sample ig-typography" >
<div className ="container fill" >
<IgrHierarchicalGrid
autoGenerate ="false"
data ={this.singersData}
primaryKey ="ID"
sortingExpressions ={this.sortingExpression1}
ref ={this.hierarchicalGrid1Ref} >
<IgrColumn
field ="Artist"
header ="Artist"
dataType ="String"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="Photo"
header ="Photo"
dataType ="Image" >
</IgrColumn >
<IgrColumn
field ="Debut"
header ="Debut"
dataType ="Number"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="GrammyNominations"
header ="Grammy Nominations"
dataType ="Number"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="GrammyAwards"
header ="Grammy Awards"
dataType ="Number"
sortable ="true" >
</IgrColumn >
<IgrRowIsland
childDataKey ="Albums"
autoGenerate ="false" >
<IgrColumn
field ="Album"
header ="Album"
dataType ="String"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="LaunchDate"
header ="Launch Date"
dataType ="Date"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="BillboardReview"
header ="Billboard Review"
dataType ="String"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="USBillboard200"
header ="US Billboard 200"
dataType ="String"
sortable ="true" >
</IgrColumn >
<IgrRowIsland
childDataKey ="Songs"
autoGenerate ="false" >
<IgrColumn
field ="Number"
header ="No."
dataType ="String"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="Title"
header ="Title"
dataType ="String"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="Released"
header ="Released"
dataType ="Date"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="Genre"
header ="Genre"
dataType ="String"
sortable ="true" >
</IgrColumn >
</IgrRowIsland >
</IgrRowIsland >
<IgrRowIsland
childDataKey ="Tours"
autoGenerate ="false" >
<IgrColumn
field ="Tour"
header ="Tour"
dataType ="String"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="StartedOn"
header ="Started on"
dataType ="String"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="Location"
header ="Location"
dataType ="String"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="Headliner"
header ="Headliner"
dataType ="String"
sortable ="true" >
</IgrColumn >
</IgrRowIsland >
</IgrHierarchicalGrid >
</div >
</div >
);
}
private _singersData: any [] = SingersData;
public get singersData(): any [] {
return this ._singersData;
}
}
const root = ReactDOM.createRoot (document.getElementById('root' ));
root.render (<Sample /> );
tsx コピー
Sorting through the API
You can sort any column or a combination of columns through the IgrHierarchicalGrid
API using the IgrHierarchicalGrid
sort
method:
import { SortingDirection } from "igniteui-react-grids" ;
tsx
hierarchicalGridRef.current.sort([{ fieldName: 'ProductName' , dir: SortingDirection.Asc, ignoreCase: true }]);
hierarchicalGridRef.current.sort([
{ fieldName: 'ProductName' , dir: SortingDirection.Asc, ignoreCase: true },
{ fieldName: 'Price' , dir: SortingDirection.Desc }
]);
tsx
Sorting is performed using our DefaultSortingStrategy algorithm. Any IgrColumn or ISortingExpression can use a custom implementation of the ISortingStrategy as a substitute algorithm. This is useful when custom sorting needs to be defined for complex template columns, or image columns, for example.
As with the filtering behavior, you can clear the sorting state by using the clearSort
method:
hierarchicalGridRef.current.clearSort('ProductName' );
hierarchicalGridRef.current.clearSort();
tsx
The sortStrategy of the IgrHierarchicalGrid is of different type compared to the sortStrategy of the IgrColumn, since they work in different scopes and expose different parameters.
The sorting operation DOES NOT change the underlying data source of the IgrHierarchicalGrid.
Initial Sorting State
It is possible to set the initial sorting state of the IgrHierarchicalGrid
by passing an array of sorting expressions to the sortingExpressions
property of the IgrHierarchicalGrid
.
useEffect(() => {
hierarchicalGridRef.current.sortingExpressions = [
{ fieldName: 'UnitsInStock' , dir: SortingDirection.Asc, ignoreCase: true },
{ fieldName: 'ProductName' , dir: SortingDirection.Desc }
];
}, [])
tsx
If values of type string are used by a column of dataType Date, the IgrHierarchicalGrid won't parse them to Date objects and using IgrHierarchicalGrid Sorting won't work as expected. If you want to use string objects, additional logic should be implemented on an application level, in order to parse the values to Date objects.
Sorting Indicators Templates
The sorting indicator icon in the column header can be customized using a template. The following properties are available for templating the sorting indicator for any sorting state (ascending, descending, none):
function sortHeaderIconTemplate(ctx: IgrGridHeaderTemplateContext) {
return (
<>
<IgrIcon name ='unfold_more' > </IgrIcon >
</>
);
}
<IgrHierarchicalGrid sortHeaderIconTemplate ={sortHeaderIconTemplate} > </IgrHierarchicalGrid >
tsx
function sortAscendingHeaderIconTemplate(ctx: IgrGridHeaderTemplateContext) {
return (
<>
<IgrIcon name ='expand_less' > </IgrIcon >
</>
);
}
<IgrHierarchicalGrid sortAscendingHeaderIconTemplate ={sortAscendingHeaderIconTemplate} > </IgrHierarchicalGrid >
tsx
function sortDescendingHeaderIconTemplate(ctx: IgrGridHeaderTemplateContext) {
return (
<>
<IgrIcon name ='expand_more' > </IgrIcon >
</>
);
}
<IgrHierarchicalGrid sortDescendingHeaderIconTemplate ={sortDescendingHeaderIconTemplate} > </IgrHierarchicalGrid >
tsx
Styling
In addition to the predefined themes, the grid could be further customized by setting some of the available CSS properties .
In case you would like to change some of the colors, you need to set a class for the grid first:
<IgrHierarchicalGrid className ="grid" >
</IgrHierarchicalGrid >
tsx
Then set the related CSS properties to this class:
.grid {
--ig-grid-sorted-header -icon -color : #ffb06a ;
--ig-grid-sortable-header -icon -hover-color : black;
}
css
Demo
import React from 'react' ;
import ReactDOM from 'react-dom/client' ;
import './index.css' ;
import { IgrHierarchicalGridModule } from "@infragistics/igniteui-react-grids" ;
import { IgrHierarchicalGrid, IgrSortingExpression, SortingDirection, IgrColumn, IgrRowIsland } from "@infragistics/igniteui-react-grids" ;
import SingersData from './SingersData.json' ;
import "@infragistics/igniteui-react-grids/grids/combined" ;
import "@infragistics/igniteui-react-grids/grids/themes/light/bootstrap.css" ;
const mods : any [] = [
IgrHierarchicalGridModule
];
mods.forEach((m) => m.register());
export default class Sample extends React.Component <any, any> {
private hierarchicalGrid: IgrHierarchicalGrid
private hierarchicalGridRef(r: IgrHierarchicalGrid) {
this .hierarchicalGrid = r;
this .setState({});
}
private _sortingExpression1: IgrSortingExpression[] | null = null ;
public get sortingExpression1(): IgrSortingExpression[] {
if (this ._sortingExpression1 == null )
{
let sortingExpression1 : IgrSortingExpression [] = [];
var sortingExpression2: IgrSortingExpression = {} as IgrSortingExpression;
sortingExpression2.fieldName = "Artist" ;
sortingExpression2.dir = SortingDirection.Asc;
sortingExpression2.ignoreCase = true ;
sortingExpression1.push(sortingExpression2)
this ._sortingExpression1 = sortingExpression1;
}
return this ._sortingExpression1;
}
constructor (props: any ) {
super (props);
this .hierarchicalGridRef = this .hierarchicalGridRef.bind(this );
}
public render (): JSX .Element {
return (
<div className ="container sample ig-typography" >
<div className ="container fill" >
<IgrHierarchicalGrid
autoGenerate ="false"
data ={this.singersData}
ref ={this.hierarchicalGridRef}
id ="hierarchicalGrid"
primaryKey ="ID"
sortingExpressions ={this.sortingExpression1} >
<IgrColumn
field ="Artist"
header ="Artist"
dataType ="String"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="Photo"
header ="Photo"
dataType ="Image" >
</IgrColumn >
<IgrColumn
field ="Debut"
header ="Debut"
dataType ="Number"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="GrammyNominations"
header ="Grammy Nominations"
dataType ="Number"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="GrammyAwards"
header ="Grammy Awards"
dataType ="Number"
sortable ="true" >
</IgrColumn >
<IgrRowIsland
childDataKey ="Albums"
autoGenerate ="false" >
<IgrColumn
field ="Album"
header ="Album"
dataType ="String"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="LaunchDate"
header ="Launch Date"
dataType ="Date"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="BillboardReview"
header ="Billboard Review"
dataType ="String"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="USBillboard200"
header ="US Billboard 200"
dataType ="String"
sortable ="true" >
</IgrColumn >
<IgrRowIsland
childDataKey ="Songs"
autoGenerate ="false" >
<IgrColumn
field ="Number"
header ="No."
dataType ="String"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="Title"
header ="Title"
dataType ="String"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="Released"
header ="Released"
dataType ="Date"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="Genre"
header ="Genre"
dataType ="String"
sortable ="true" >
</IgrColumn >
</IgrRowIsland >
</IgrRowIsland >
<IgrRowIsland
childDataKey ="Tours"
autoGenerate ="false" >
<IgrColumn
field ="Tour"
header ="Tour"
dataType ="String"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="StartedOn"
header ="Started on"
dataType ="String"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="Location"
header ="Location"
dataType ="String"
sortable ="true" >
</IgrColumn >
<IgrColumn
field ="Headliner"
header ="Headliner"
dataType ="String"
sortable ="true" >
</IgrColumn >
</IgrRowIsland >
</IgrHierarchicalGrid >
</div >
</div >
);
}
private _singersData: any [] = SingersData;
public get singersData(): any [] {
return this ._singersData;
}
}
const root = ReactDOM.createRoot (document.getElementById('root' ));
root.render (<Sample /> );
tsx コピー
#hierarchicalGrid {
--ig-grid-sorted-header -icon -color : #ffb06a ;
--ig-grid-sortable-header -icon -hover-color : black;
}
css コピー
API References
Additional Resources
Our community is active and always welcoming to new ideas.