SAKURA
SAKURA

Reputation: 986

React-Table: Select Single Row Only, Disable Multiple Row Selection

I am using radio buttons to select the rows. How do I disable multiple row selection so only one row can be selected at a time?

I am using selectedFlatRows, but it's allowing for multiple row selection.

const Table = props => {
  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    page,
    prepareRow,
    selectedFlatRows,
  } = useTable(
    {
      columns,
      data: props.linkedProducts,
    },
    useSortBy,
    usePagination,
    useRowSelect,
    hooks => {
      hooks.visibleColumns.push(columns => [
        {
          id: 'selection',
          disableGlobalFilter: true,
          accessor: 'selection',
          Cell: ({row}) => (
            <RadioButton
              {...row.getToggleRowSelectedProps()}
            />
          ),
        },
        ...columns,
      ]);
    }
  );

Upvotes: 4

Views: 5396

Answers (4)

Rahmlad Aramide
Rahmlad Aramide

Reputation: 581

Tanstack table already has a prebuilt table option that handles that, which is enableMultiRowSelection and it can be used in 2 ways, either by:

  • Passing a boolean value to either or not allow multiple row selection
  • A function that given a row, returns whether to enable/disable multiple row selection for that row's children/grandchildren.

Here's an example of where I used the first use case of it:

const { table } = useCustomTable({
    multiRows: false,
    ...
});

From the snippet above, the multiRows variable was used to pass in the boolean function, then in my useReactTable props, I'm assigning the enableMultiRowSelection option the multiRows prop value as shown below:

function useCustomTable({ tableData, columns, multiRows=true }: ITableProps) {
const data = useMemo(() => tableData || [], [tableData]);

const table = useReactTable({
    data,
    columns,
    enableMultiRowSelection: multiRows,
    ...
  });
  return { table };
}

export { useCustomTable };

You can read more from their official documentation: Tanstack Table Options

Upvotes: 1

Ultimate Fire
Ultimate Fire

Reputation: 281

You have to do like this by my experience.

Cell: ({row}) => (
   <RadioButton
      {...row.getToggleRowSelectedProps({
         onChange: () => {
           const selected = row.isSelected; // get selected status of current row.
           toggleAllRowsSelected(false); // deselect all.
           row.toggleRowSelected(!selected); // reverse selected status of current row.
         },
      })}
   />
)

Upvotes: 1

sinewave440hz
sinewave440hz

Reputation: 1365

I was puzzling over this one for a while, the solution I used seems to work fine and is very simple. Use the following in your onClick() method:

  onClick={() => {
    toggleAllRowsSelected(false);
    row.toggleRowSelected();
  }

You'll need to include toggleAllRowsSelected when destructuring the variables from useTable.

 const { toggleAllRowsSelected, selectedFlatRows,...} = useTable({ columns, data, ....}

Upvotes: 5

SAKURA
SAKURA

Reputation: 986

I used a workaround to make this work, basically setting the selected rowId in the state.

const [selectedRowId, setSelectedRowId] = useState('0');

const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    rows,
    prepareRow,
  } = useTable(
    {
      columns,
      data,
    },
    usePagination
  );

This is a shortened version of the code for the table. As you can see it sets state whenever the user clicks on the row or checks the radio button.

<TableV2.Body {...getTableBodyProps()}>
            {rows.map((row) => {
              prepareRow(row);
              return (
                <TableV2.Row
                  key={row.id}
                  onClick={() => setSelectedRowId(row.id)}
                  {...row.getRowProps()}
                  bg={row.id !== selectedRowId ? 'white' : 'gray.10'}
                >
                  <TableV2.Cell key={`${row.id}-radio`}>
                    <Box testIds={{test: 'sku-detail-radio-button'}} mt={-12}>
                      <RadioButton
                        value={row.id}
                        checked={row.id === selectedRowId}
                        onChange={() => setSelectedRowId(row.id)}
                      />
                    </Box>
                  </TableV2.Cell>

If you want to pass the selectedRowId to the parent component, you can use useEffect:

 useEffect(() => {
        props.onRowSelection(selectedRowId);
      }, [props, selectedRowId]);

Upvotes: 0

Related Questions