Sorting

The react-bootstrap-data-grid grid component implements interactive sorting of the rows in a grid. Sorting can be done on a single column at a time.

Enabling

Sorting for a grid is disabled by default. To enable sorting, enabling must be done for both the Grid component and for individual columns inside the grid.

To enable sorting for individual columns, set the sortable property to true for the ColDef object for each column for which you wish to enable sorting.

export const heroColumns: ColDef[] = [
  // other columns
  {
    type: "number",
    name: "damageMinLv1",
    label: "Damage Min Lv 1",
    width: 150,
    sortable: true
  },
  // other columns
];

To enable sorting for a Grid component, set the sortModel prop. See the following section for examples.

Controlled vs Uncontrolled

Like for several other features of react-bootstrap-data-grid, here are two ways to configure sorting for a grid component, controlled and uncontrolled.

Controlled mode maximizes customizability by exposing the state and setter function to the parent component of the Grid component. Configure a grid to sort in controlled mode by passing a prop of type ControlledSortModel.

const SortDemoGrid: FC = () => {
  const [sortColDef, setSortColDef] = useState<SortColDef | null>(null);
 
  return (
    <Grid
      rows={rows}
      cols={heroColumns}
      width="parent"
      sortModel={{ type: "controlled", sortColDef, setSortColDef }}
    />
  );
};

Uncontrolled mode reduces the amount of code needed to configure sorting at the cost of the parent component losing the ability to directly configure the column being sorted. Instead, the state of column being sorted is stored in the Grid component itself. To enable sorting for a grid in uncontrolled mode, pass an UncontrolledSortModel as the sortModel prop.

const SortDemoGrid: FC = () => {
  return (
    <Grid
      rows={rows}
      cols={heroColumns}
      width="parent"
      sortModel={{ type: "uncontrolled", initialSortColDef: null }}
    />
  );
};

UI

The user may change the sort order for a grid by clicking on the header cell to cycle between sorting in the following order:

  • ascending
  • descending
  • none

One may also use keyboard navigation to select the header cell to control and then use the key bindings for clicking on a button, generally Enter or Space, to cycle through sort orders with a keyboard.

Example

Live Demo

Abomination
No
None
26
5
7.5
5
0
7
7
8
8
9
2
3
4
5
6
6
7
8
10
11
11
13
15
18
20
40
60
30
20
40
20
67
10
Antiquarian
No
Skeleton Key
17
3
10
5
0
5
5
6
6
7
1
2
3
4
5
3
4
4
5
5
5
6
7
8
9
20
20
20
20
20
20
67
10
Arbalest
No
Bandage
27
5
0
5
0
3
3
4
4
5
6
7
8
9
10
4
5
6
6
7
8
10
11
13
14
40
30
30
30
40
30
67
10
Bounty Hunter
No
None
25
5
5
5
0
5
5
6
6
7
4
5
6
7
8
5
6
7
7
8
10
12
13
15
16
40
30
30
20
40
30
67
40
Crusader
Yes
Holy Water
33
7
5
5
0
1
1
2
2
3
3
4
5
6
7
6
7
8
9
10
12
14
16
17
19
40
30
30
30
40
30
67
10
Duelist
No
None
21
4
5
5
0
6
6
7
7
8
5
6
7
8
9
5
6
7
7
8
7
8
10
11
13
30
30
30
30
30
40
67
10
Flagellant
Yes
None
22
4
0
5
0
6
6
8
8
9
2
3
4
5
6
3
4
4
5
5
6
7
8
10
11
50
30
65
40
50
30
73
0
Grave Robber
No
Shovel
20
4
10
5
0
8
8
9
9
10
6
7
8
9
10
4
5
6
6
7
8
10
11
13
14
20
50
30
30
20
30
67
50
Hellion
No
None
26
5
10
5
0
4
4
5
5
6
5
6
7
8
9
6
7
8
9
10
12
14
16
17
19
40
40
40
30
40
30
67
20
Highwayman
No
None
23
5
10
5
0
5
5
6
6
7
5
6
7
8
9
5
6
7
8
9
10
12
13
15
16
30
30
30
30
30
30
67
40
Houndmaster
No
2 Dog Treats
21
4
10
5
0
5
5
6
6
7
4
5
6
7
8
4
5
6
6
7
7
8
10
11
13
40
40
40
30
40
30
67
40
Jester
No
Medicinal Herbs
19
4
15
5
0
7
7
8
8
9
4
5
6
7
8
4
5
6
6
7
7
8
10
11
13
20
40
30
20
20
40
67
30
Leper
Yes
Medicinal Herbs
35
7
0
5
0
2
2
3
3
4
1
2
3
4
5
8
9
10
12
13
16
18
21
23
26
60
40
10
20
60
40
67
10
Man-at-Arms
No
None
31
6
5
5
0
3
3
4
4
5
2
3
4
5
6
5
6
7
7
8
9
10
12
13
14
40
30
40
30
40
30
67
10
Musketeer
No
Bandage
27
5
0
5
0
3
3
4
4
5
6
7
8
9
10
4
5
6
6
7
8
10
11
13
14
40
30
30
30
40
30
67
10
Occultist
No
None
19
4
10
5
0
6
6
7
7
8
6
7
8
9
10
4
5
6
6
7
7
8
10
11
13
20
30
40
40
20
60
67
10
Plague Doctor
No
Antivenom
22
4
0
5
0
7
7
8
8
9
2
3
4
5
6
4
5
6
6
7
7
8
10
11
13
20
60
20
50
20
50
67
20
Runaway
No
Torch
22
4
5
5
0
5
5
6
6
7
4
5
5
7
8
4
5
6
6
7
7
8
10
11
13
20
40
40
30
30
20
67
30
Shieldbreaker
No
None
20
4
8
5
0
5
6
8
8
9
6
7
8
9
10
5
6
7
8
9
10
12
14
16
18
50
20
30
30
50
30
67
20
Vestal
Yes
None
24
5
0
5
0
4
4
5
5
6
1
2
3
4
5
4
5
6
6
7
8
10
11
13
14
30
30
40
30
30
30
67
10

Code

import { Grid, RowDef, ColDef } from "@absreim/react-bootstrap-data-grid";
import heroData from "./heroes.json";
import { Hero } from "./types";
import { FC } from "react";
 
export const heroColumns: ColDef[] = [
  { type: "string", name: "hero", label: "Hero", width: 140 },
  { type: "string", name: "religious", label: "Religious", width: 110 },
  { type: "string", name: "provisions", label: "Provisions", width: 150 },
  { type: "number", name: "maxHp", label: "Max HP", width: 100 },
  { type: "number", name: "maxHpPerRank", label: "HP / Rank", width: 110 },
  { type: "number", name: "dodge", label: "Dodge", width: 90 },
  { type: "number", name: "dodgePerRank", label: "Dodge / Rank", width: 130 },
  { type: "number", name: "protection", label: "Protection", width: 120 },
  { type: "number", name: "speedLv1", label: "Speed Lv 1", width: 120 },
  { type: "number", name: "speedLv2", label: "Speed Lv 2", width: 120 },
  { type: "number", name: "speedLv3", label: "Speed Lv 3", width: 120 },
  { type: "number", name: "speedLv4", label: "Speed Lv 4", width: 120 },
  { type: "number", name: "speedLv5", label: "Speed Lv 5", width: 120 },
  { type: "number", name: "critLv1", label: "Crit % Lv 1", width: 120 },
  { type: "number", name: "critLv2", label: "Crit % Lv 2", width: 120 },
  { type: "number", name: "critLv3", label: "Crit % Lv 3", width: 120 },
  { type: "number", name: "critLv4", label: "Crit % Lv 4", width: 120 },
  { type: "number", name: "critLv5", label: "Crit % Lv 5", width: 120 },
  {
    type: "number",
    name: "damageMinLv1",
    label: "Damage Min Lv 1",
    width: 150,
  },
  {
    type: "number",
    name: "damageMinLv2",
    label: "Damage Min Lv 2",
    width: 150,
  },
  {
    type: "number",
    name: "damageMinLv3",
    label: "Damage Min Lv 3",
    width: 150,
  },
  {
    type: "number",
    name: "damageMinLv4",
    label: "Damage Min Lv 4",
    width: 150,
  },
  {
    type: "number",
    name: "damageMinLv5",
    label: "Damage Min Lv 5",
    width: 150,
  },
  {
    type: "number",
    name: "damageMaxLv1",
    label: "Damage Max Lv 1",
    width: 150,
  },
  {
    type: "number",
    name: "damageMaxLv2",
    label: "Damage Max Lv 2",
    width: 150,
  },
  {
    type: "number",
    name: "damageMaxLv3",
    label: "Damage Max Lv 3",
    width: 150,
  },
  {
    type: "number",
    name: "damageMaxLv4",
    label: "Damage Max Lv 4",
    width: 150,
  },
  {
    type: "number",
    name: "damageMaxLv5",
    label: "Damage Max Lv 5",
    width: 150,
  },
  { type: "number", name: "stunRes", label: "Stun Res %", width: 120 },
  { type: "number", name: "blightRes", label: "Blight Res %", width: 130 },
  { type: "number", name: "bleedRes", label: "Bleed Res %", width: 130 },
  { type: "number", name: "diseaseRes", label: "Disease Res %", width: 140 },
  { type: "number", name: "moveRes", label: "Move Res %", width: 120 },
  { type: "number", name: "debuffRes", label: "Debuff Res %", width: 130 },
  {
    type: "number",
    name: "deathblowRes",
    label: "Deathblow Res %",
    width: 150,
  },
  { type: "number", name: "trapRes", label: "Trap Res %", width: 120 },
];
 
heroColumns.forEach((hero) => {
  hero.sortable = true;
});
 
const rows: RowDef<Hero>[] = heroData.map((hero) => ({
  id: hero.hero,
  data: hero,
}));
 
const SortDemoGrid: FC = () => (
  <Grid
    rows={rows}
    cols={heroColumns}
    width="parent"
    height={700}
    sortModel={{ type: "uncontrolled", initialSortColDef: null }}
  />
);
 
export default SortDemoGrid;