MRT logoMaterial React Table

On This Page

    Row Selection Guide

    Material React Table has a built-in row selection feature and makes it easy to manage the selection state yourself. This guide demonstrates how to enable row selection and customize the selection behavior.

    Relevant Table Options

    1
    boolean
    true
    MRT Row Selection Docs
    2
    boolean
    true
    MRT Row Selection Docs
    3
    boolean | (row: MRT_Row) => boolean
    MRT Row Selection Docs
    4
    boolean
    true
    5
    boolean
    true
    6
    (originalRow: TData, index: number, parent?: MRT_Row<TData>) => string
    TanStack Table Core Table Docs
    7
    CheckboxProps | ({ table }) => CheckboxProps
    Material UI Checkbox Props
    8
    CheckboxProps | ({ row, table }) => CheckboxProps
    Material UI Checkbox Props
    9
    OnChangeFn<RowSelectionState>
    TanStack Table Row Selection Docs
    10
    'bottom' | 'top' | 'none'
    'top'
    11
    ({ table, groupedAlert, selectedAlert }) => ReactNode
    12
    'sticky' | 'top' | 'bottom' | 'top-and-bottom' | 'select-sticky' | 'select-top' | 'select-bottom'
    'sticky'
    13
    'all' | 'page'
    'page'

    Relevant State

    1
    Record<string, boolean>
    {}
    TanStack Table Row Selection Docs

    Enable Row Selection

    Selection checkboxes can be enabled with the enableRowSelection table option.

    const table = useMaterialReactTable({
    columns,
    data,
    enableRowSelection: true,
    });
    return <MaterialReactTable table={table} />;

    Enable Row Selection Conditionally Per Row

    You can also enable row selection conditionally per row with the same enableRowSelection table option, but with a callback function instead of a boolean.

    const table = useMaterialReactTable({
    columns,
    data,
    enableRowSelection: (row) => row.original.age > 18, //disable row selection for rows with age <= 18
    });

    Batch Row Selection

    New in v2.11.0

    By default, when the user holds down the Shift key and clicks a row, all rows between the last selected row and the clicked row will be selected. This can be disabled with the enableBatchRowSelection table option.

    const table = useMantineReactTable({
    columns,
    data,
    enableRowSelection: true,
    enableBatchRowSelection: false, //disable batch row selection with shift key
    });

    Access Row Selection State

    There are two ways to access the selection state. You can either manage the selection state yourself or read it from the table instance.

    Manage Row Selection State

    The row selection state is managed internally by default, but you will more than likely want to have access to that state yourself. Here is how you can simply get access to the row selection state, specifically:

    const [rowSelection, setRowSelection] = useState<MRT_RowSelectionState>({}); //ts type available
    const table = useMaterialReactTable({
    columns,
    data,
    enableRowSelection: true,
    onRowSelectionChange: setRowSelection,
    state: { rowSelection },
    });
    return <MaterialReactTable table={table} />;

    Read Row Selection State from Table Instance

    Alternatively, you can read the selection state directly from the table instance like so:

    const table = useMaterialReactTable({
    columns,
    data,
    enableRowSelection: true,
    renderTopToolbarCustomActions: ({ table }) => (
    <Button
    onClick={() => {
    const rowSelection = table.getState().rowSelection; //read state
    const selectedRows = table.getSelectedRowModel().rows; //or read entire rows
    }}
    >
    Download Selected Users
    </Button>
    ),
    });
    useEffect(() => {
    //fetch data based on row selection state or something
    }, [table.getState().rowSelection]);
    return <MaterialReactTable table={table} />;

    Note: table.getSelectedRowModel().rows only really works with client-side pagination. Use rowSelection state if you are using server-side pagination. Row Models only contain rows based on the data you pass in.

    Useful Row IDs

    By default, the row.id for each row in the table is simply the index of the row in the table. You can override this and instruct Material React Table to use a more useful Row ID with the getRowId table option. For example, you may want something like this:

    const table = useMaterialReactTable({
    columns,
    data,
    enableRowSelection: true,
    getRowId: (originalRow) => originalRow.userId,
    });

    As rows get selected, the rowSelection state will look like this:

    {
    "3f25309c-8fa1-470f-811e-cdb082ab9017": true,
    "be731030-df83-419c-b3d6-9ef04e7f4a9f": true,
    ...
    }

    This can be very useful when you are trying to read your selection state and do something with your data as the row selection changes.

    Demo

    Open StackblitzOpen Code SandboxOpen on GitHub
    DylanMurray22261 Erdman FordEast DaphneKentucky
    RaquelKohler18769 Dominic GroveColumbusOhio
    1-2 of 2

    Source Code

    1import { useEffect, useMemo, useState } from 'react';
    2import {
    3 MaterialReactTable,
    4 useMaterialReactTable,
    5 type MRT_ColumnDef,
    6 type MRT_RowSelectionState,
    7} from 'material-react-table';
    8
    9//data definitions...
    20
    21const data = [
    22 {
    23 userId: '3f25309c-8fa1-470f-811e-cdb082ab9017', //we'll use this as a unique row id
    24 firstName: 'Dylan',
    25 lastName: 'Murray',
    26 age: 22,
    27 address: '261 Erdman Ford',
    28 city: 'East Daphne',
    29 state: 'Kentucky',
    30 }, //data definitions...
    41];
    42
    43const Example = () => {
    44 const columns = useMemo<MRT_ColumnDef<Person>[]>(
    45 //column definitions...
    73 );
    74
    75 //optionally, you can manage the row selection state yourself
    76 const [rowSelection, setRowSelection] = useState<MRT_RowSelectionState>({});
    77
    78 const table = useMaterialReactTable({
    79 columns,
    80 data,
    81 enableRowSelection: true,
    82 getRowId: (row) => row.userId, //give each row a more useful id
    83 onRowSelectionChange: setRowSelection, //connect internal row selection state to your own
    84 state: { rowSelection }, //pass our managed row selection state to the table to use
    85 });
    86
    87 //do something when the row selection changes...
    88 useEffect(() => {
    89 console.info({ rowSelection }); //read your managed row selection state
    90 // console.info(table.getState().rowSelection); //alternate way to get the row selection state
    91 }, [rowSelection]);
    92
    93 return <MaterialReactTable table={table} />;
    94};
    95
    96export default Example;
    97

    Select Row on Row Click

    By default, a row can only be selected by either clicking the checkbox or radio button in the mrt-row-select column. If you want to be able to select a row by clicking anywhere on the row, you can add your own onClick function to a table body row like this:

    const table = useMaterialReactTable({
    columns,
    data,
    enableRowSelection: true,
    //clicking anywhere on the row will select it
    muiTableBodyRowProps: ({ row, staticRowIndex, table }) => ({
    onClick: (event) =>
    getMRT_RowSelectionHandler({ row, staticRowIndex, table })(event), //import this helper function from material-react-table
    sx: { cursor: 'pointer' },
    }),
    });

    Disable Select All

    By default, if you enable selection for each row, there will also be a select all checkbox in the header of the checkbox column. It can be hidden with the enableSelectAll table option.

    const table = useMaterialReactTable({
    columns,
    data,
    enableRowSelection: true,
    enableSelectAll: false,
    });

    Position or Hide Alert Banner Selection Message

    By default, an alert banner will be show as rows are selected. You can use the positionToolbarAlertBanner table option to show the alert banner in the top toolbar, bottom toolbar, as an overlay in the table head, or hide it completely.

    const table = useMaterialReactTable({
    columns,
    data,
    enableRowSelection: true,
    positionToolbarAlertBanner: 'head-overlay', //show alert banner over table head, top toolbar, or bottom toolbar
    });

    Single Row Selection

    By default, the enableMultiRowSelection table option is set to true, which means that multiple rows can be selected at once with a checkbox. If you want to only allow a single row to be selected at a time, you can set this table option to false and a radio button will be used instead of a checkbox.

    const table = useMaterialReactTable({
    columns,
    data,
    enableMultiRowSelection: false, //shows radio buttons instead of checkboxes
    enableRowSelection: true,
    });

    Demo

    DylanMurray22261 Erdman FordEast DaphneKentucky
    RaquelKohler18769 Dominic GroveColumbusOhio
    1-2 of 2

    Source Code

    1import { useMemo, useState } from 'react';
    2import {
    3 MaterialReactTable,
    4 useMaterialReactTable,
    5 type MRT_ColumnDef,
    6 type MRT_RowSelectionState,
    7} from 'material-react-table';
    8
    9//data definitions...
    20
    21const data = [
    22 //data definitions...
    42];
    43
    44const Example = () => {
    45 const columns = useMemo<MRT_ColumnDef<Person>[]>(
    46 //column definitions...
    74 );
    75
    76 //optionally, you can manage the row selection state yourself
    77 const [rowSelection, setRowSelection] = useState<MRT_RowSelectionState>({});
    78
    79 const table = useMaterialReactTable({
    80 columns,
    81 data,
    82 enableRowSelection: true,
    83 enableMultiRowSelection: false, //use radio buttons instead of checkboxes
    84 getRowId: (row) => row.userId, //give each row a more useful id
    85 muiTableBodyRowProps: ({ row }) => ({
    86 //add onClick to row to select upon clicking anywhere in the row
    87 onClick: row.getToggleSelectedHandler(),
    88 sx: { cursor: 'pointer' },
    89 }),
    90 positionToolbarAlertBanner: 'bottom', //move the alert banner to the bottom
    91 onRowSelectionChange: setRowSelection, //connect internal row selection state to your own
    92 state: { rowSelection }, //pass our managed row selection state to the table to use
    93 });
    94
    95 return <MaterialReactTable table={table} />;
    96};
    97
    98export default Example;
    99

    Customize Select Checkboxes or Radio Buttons

    The selection checkboxes can be customized with the muiSelectCheckboxProps table option. Any prop that can be passed to a Mui Checkbox component can be specified here. For example, you may want to use a different color for the checkbox or use some logic to disable certain rows from being selected.

    const table = useMaterialReactTable({
    columns,
    data,
    enableRowSelection: true,
    muiSelectCheckboxProps: {
    color: 'secondary',
    },
    });

    Demo

    DylanMurray22261 Erdman FordEast DaphneKentucky
    RaquelKohler18769 Dominic GroveColumbusOhio
    ErvinReinger20566 Brakus InletSouth LindaWest Virginia
    BrittanyMcCullough21722 Emie StreamLincolnNebraska
    BransonFrami3232188 Larkin TurnpikeCharlestonSouth Carolina
    1-5 of 5

    Source Code

    1import { useMemo } from 'react';
    2import {
    3 MaterialReactTable,
    4 useMaterialReactTable,
    5 type MRT_ColumnDef,
    6} from 'material-react-table';
    7import { data, type Person } from './makeData';
    8
    9const Example = () => {
    10 const columns = useMemo<MRT_ColumnDef<Person>[]>(
    11 //column definitions...
    40 );
    41
    42 const table = useMaterialReactTable({
    43 columns,
    44 data,
    45 enableSelectAll: false,
    46 enableRowSelection: (row) => row.original.age >= 21, //enable row selection conditionally per row
    47 muiSelectCheckboxProps: { color: 'secondary' },
    48 positionToolbarAlertBanner: 'head-overlay',
    49 });
    50
    51 return <MaterialReactTable table={table} />;
    52};
    53
    54export default Example;
    55

    Manual Row Selection Without Checkboxes

    You may have a use case where you want to be able to select rows by clicking them, but you do not want to show any checkboxes or radio buttons. You can do this by implementing a row selection feature yourself while keeping the enableRowSelection table option false so that the default selection behavior is disabled.

    Demo

    DylanMurray22261 Erdman FordEast DaphneKentucky
    RaquelKohler18769 Dominic GroveColumbusOhio
    1-2 of 2

    Source Code

    1import { useMemo, useState } from 'react';
    2import {
    3 MaterialReactTable,
    4 useMaterialReactTable,
    5 type MRT_ColumnDef,
    6 type MRT_RowSelectionState,
    7} from 'material-react-table';
    8
    9//data definitions...
    20
    21const data = [
    22 //data definitions...
    42];
    43
    44const Example = () => {
    45 const columns = useMemo<MRT_ColumnDef<Person>[]>(
    46 //column definitions...
    75 );
    76
    77 const [rowSelection, setRowSelection] = useState<MRT_RowSelectionState>({});
    78
    79 const table = useMaterialReactTable({
    80 columns,
    81 data,
    82 getRowId: (row) => row.userId,
    83 muiTableBodyRowProps: ({ row }) => ({
    84 //implement row selection click events manually
    85 onClick: () =>
    86 setRowSelection((prev) => ({
    87 ...prev,
    88 [row.id]: !prev[row.id], //this is a simple toggle implementation
    89 })),
    90 selected: rowSelection[row.id],
    91 sx: {
    92 cursor: 'pointer',
    93 },
    94 }),
    95 onRowSelectionChange: setRowSelection,
    96 state: { rowSelection },
    97 });
    98
    99 return <MaterialReactTable table={table} />;
    100};
    101
    102export default Example;
    103

    Sticky Pinned Row Selection

    You can combine the row pinning feature with the row selection feature to create a cool user experience where selected rows always stay within view.

    Demo

    DylanMurraydmurray@yopmail.comEast Daphne
    RaquelKohlerrkholer33@yopmail.comColumbus
    ErvinReingerereinger@mailinator.comSouth Linda
    BrittanyMcCulloughbmccullough44@mailinator.comLincoln
    BransonFramibframi@yopmain.comNew York
    BenMurraybenm@email.comSalt Lake City
    ElenaSmithesmith@yopmail.comLos Angeles
    MichaelJohnsonmjohnson@mailinator.comChicago
    SophiaBrownsbrown@yopmail.comHouston
    LucasDavisldavis@mailinator.comPhoenix
    OliviaGarciaogarcia@yopmail.comPhiladelphia
    LiamRodriguezlrodriguez@mailinator.comSan Antonio
    EmmaMartinezemartinez@yopmail.comSan Diego
    NoahHernandeznhernandez@mailinator.comDallas
    AvaLopezalopez@yopmail.comSan Jose
    WilliamGonzalezwgonzalez@mailinator.comAustin
    IsabellaWilsoniwilson@yopmail.comJacksonville
    JamesAndersonjanderson@mailinator.comFort Worth
    MiaThomasmthomas@yopmail.comColumbus
    AlexanderTaylorataylor@mailinator.comCharlotte
    GraceMooregmoore@yopmail.comIndianapolis
    EthanWhiteewhite@mailinator.comSan Francisco
    LilyHarrislharris@yopmail.comSeattle
    DanielMartindmartin@mailinator.comDenver
    ZoeJacksonzjackson@yopmail.comBoston
    MatthewThompsonmthompson@mailinator.comNashville
    EllaGarciaegarcia@yopmail.comDetroit
    DavidMartinezdmartinez@mailinator.comPortland
    AriaRobinsonarobinson@yopmail.comLas Vegas
    JosephClarkjclark@mailinator.comBaltimore

    Source Code

    1import { useMemo } from 'react';
    2import {
    3 MaterialReactTable,
    4 useMaterialReactTable,
    5 type MRT_ColumnDef,
    6} from 'material-react-table';
    7import { data, type Person } from './makeData';
    8
    9const Example = () => {
    10 const columns = useMemo<MRT_ColumnDef<Person>[]>(
    11 //column definitions...
    32 );
    33
    34 const table = useMaterialReactTable({
    35 columns,
    36 data,
    37 enablePagination: false,
    38 enableRowPinning: true,
    39 enableRowSelection: true,
    40 enableStickyHeader: true,
    41 rowPinningDisplayMode: 'select-sticky',
    42 getRowId: (row) => row.email,
    43 initialState: {
    44 rowPinning: {
    45 top: ['ereinger@mailinator.com'],
    46 },
    47 rowSelection: {
    48 'ereinger@mailinator.com': true,
    49 },
    50 },
    51 muiTableContainerProps: {
    52 sx: {
    53 maxHeight: '400px',
    54 },
    55 },
    56 muiTableBodyRowProps: ({ row, table }) => {
    57 const { density } = table.getState();
    58 return {
    59 sx: {
    60 //Set a fixed height for pinned rows
    61 height: row.getIsPinned()
    62 ? `${
    63 //Default mrt row height estimates. Adjust as needed.
    64 density === 'compact' ? 37 : density === 'comfortable' ? 53 : 69
    65 }px`
    66 : undefined,
    67 },
    68 };
    69 },
    70 });
    71
    72 return <MaterialReactTable table={table} />;
    73};
    74
    75export default Example;
    76

    View Extra Storybook Examples