I'm not too familiar with useReactTable, however I need to make use of useTable to conditionally select certain rows based on some conditions.
Below is the useReactTable equivalent of what I want to achieve:
const table = useReactTable({
data,
columns,
state: {
rowSelection
},
enableRowSelection: (row) => row.original.age > 18, //This is what I want to achieve with useTable
onRowSelectionChange: setRowSelection,
getCoreRowModel: getCoreRowModel(),
getFilteredRowModel: getFilteredRowModel(),
getPaginationRowModel: getPaginationRowModel(),
debugTable: true
});
The checkbox at any particular row should only be selectable if the users age is more than 18.
How can that be achieved with useTable in React?
Thanks
Update:
I was able to get the rows disabled based on some conditions, but there is another bigger problem, which is that when I use the Select All checkbox at the top of the table, I see even the disabled checkboxes still getting checked, I don't want that. Below is a screenshot of the behavior I don't want
A disabled checkbox should never get checked even when Select All is used
You can add disabled property to checkboxes and control if they are checked not or not based on a condition. I used official row-selection-example to test.
function Table({ columns, data }) {
// Use the state and functions returned from useTable to build your UI
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow,
selectedFlatRows,
state: { selectedRowIds },
} = useTable(
{
columns,
data,
},
useRowSelect,
hooks => {
hooks.visibleColumns.push(columns => [
// Let's make a column for selection
{
id: 'selection',
// The header can use the table's getToggleAllRowsSelectedProps method
// to render a checkbox
Header: ({ getToggleAllRowsSelectedProps }) => (
<div>
<IndeterminateCheckbox {...getToggleAllRowsSelectedProps()} />
</div>
),
// Disabled and not checked if age < 13
Cell: ({ row }) => (
<div>
{row.original.age >= 13 ? <IndeterminateCheckbox {...row.getToggleRowSelectedProps()} />
: <IndeterminateCheckbox {...row.getToggleRowSelectedProps()} disabled={true} checked={row.original.age >= 13 ? true : false} />}
</div>
),
},
...columns,
])
}
)
Related
I'm using a custom toolbar with MUI Datatables and can access the currently selected rows but when I delete these rows, I want to clear the selected rows. On the current behavior, if I select and delete the first two rows (0,1), these rows are removed from the MUI Datatable but the selection change to the rows (2,3).
const options = {
filterType: 'checkbox',
customToolbarSelect: selectedRows => (
<MyCustomToolbarSelect
selectedRows={selectedRows}
onRowsDelete={deleteSelected}
/>
),
}
Turns out you can set a state variable to hold the selected rows and change the value on the onRowsDelete:
const [selectedRows, setSelectedRows] = useState([]);
const options = {
rowsSelected: selectedRows,
onRowSelectionChange: (rowsSelectedData, allRows, rowsSelected) => {
setSelectedRows(rowsSelected);
},
customToolbarSelect: () => (
<MyCustomToolbarSelect
selectedRows={selectedRows}
onRowsDelete={() => {
deleteSelected();
setSelectedRows([]);
}
/>
),
You can access an example using class components here: https://codesandbox.io/s/muidatatables-custom-toolbar-hv5n9?file=/index.js
I want a single select option column component, hence used filterComponent property of the columns-props to render a custom Single Select Material-UI component. On Change of the option the value of the Select is updated. But I also need the row data to be filtered out. How can this be achieved?
Used customFilterAndSearch prop supported by columns props, this is not getting invoked because of using filterComponent to override the existing component.
Tried calling customFilterAndSearch onChange of the select options, for this to work, customFilterAndSearch expects 2 arguments 1. option/filter value, 2. row-data. I can obtain the 1st parameter value, but is there a way to obtain row-data ?
{
title: "Birth Place",
field: "birthCity",
lookup: birthCity,
customFilterAndSearch: (data, rowData) => {
console.log({ data, rowData });
return true;
},
filterComponent: (props) => {
return (
<Select
value={city}
onChange={(e) => {
setCity(e.target.value);
props.columnDef.customFilterAndSearch(e.target.value, {}); // don't know how to idenitfy row data and send as a parameter
}}
>
{Object.keys(birthCity).map((key) => {
return <MenuItem value={key}> {key} </MenuItem>;
})}
</Select>
);
}
}
Link to codesandbox
Hi guy I just do experiment on build bulk delete on tanstack React Table
the problem is here I can't change the id of the selected column
why do I want to change this?
because I want MongoDB id that can send to the server.
with selectedRowIds method
here some code from hook
hooks => {
hooks.visibleColumns.push(columns => [
// Let's make a column for selection
{
id: 'selection',
// accessor: '_id',
// The header can use the table's getToggleAllRowsSelectedProps method
// to render a checkbox
Header: ({ getToggleAllRowsSelectedProps }) => (
<div>
<IndeterminateCheckbox {...getToggleAllRowsSelectedProps()} />
</div>
),
// The cell can use the individual row's getToggleRowSelectedProps method
// to the render a checkbox
Cell: ({ row }) => {
console.log(row)
return <div>
<IndeterminateCheckbox {...row.getToggleRowSelectedProps()} />
</div>
},
},
...columns,
])
and all full reference comes from the main documentation
use selectedFlatRows is contian all selected row data
There is an option you can pass to the useReactTable hook called getRowId that allows you to customize your row id.
getRowId?: (
originalRow: TData,
index: number,
parent?: Row<TData>
) => string
https://tanstack.com/table/v8/docs/api/core/table#getrowid
I have a table built with antd in react. I am getting the data from an API endpoint. Everything else works fine. But when i click one row at the table, all the rows are getting selected. The row selection is working fine with constant data of antd documentation. But when i plug it in my code with dynamic data rendering it just goes crazy and selects every row whenever I click on only one row.
Here is my state :
class TabularView extends React.Component {
intervalID;
state = {
selectedRowKeys: [],
loading: false,
data: [],
columns : [],
length : '',
approve : '',
perc : '',
icon : <ArrowUpOutlined/>,
color : '',
visible: false
}
Here is my other functions for the row selection
start = () => {
this.setState({ loading: true });
setTimeout(() => {
this.setState({
selectedRowKeys: [],
loading: false,
});
}, 1000);
}
onSelectChange = selectedRowKeys => {
console.log('selectedRowKeys changed: ', selectedRowKeys);
this.setState({ selectedRowKeys });
}
And here is my render part for the rowselection
render(){
const { loading, selectedRowKeys } = this.state;
const rowSelection = {
selectedRowKeys,
onChange: this.onSelectChange,
};
return(
<Table rowSelection={rowSelection} columns={this.state.columns} dataSource={this.state.data} pagination={{ pageSize: 20 }} />
)}
Use an unique key prop to each child to avoid this kind of problem
Each and every react chield or any map function you use. If you do not provide a unique key prop to it. It will give a warning.
React always understand it's children by the key prop. So as all the key to the table is the same. As you selecting one row, as the key is same it is selecting all the row. Key prop in react is very much useful for dynamic programming using map function. Please read this for more clarification - React Key Prop
You have to add key on your dataSource object.
I have an antd table where the data inside one of the columns can get pretty large. I am showing this data in full when the row is expanded but because the cell with a lot of data is on the right side of the screen and the expander icon is on the left side of the screen it is not very intuitive. What I would like to do is move the expander icon inside the actual cell so that the user knows they can click the + to see the rest of the data.
Thanks in advance.
Yes, you can and you have to dig a little deeper their docucmentation...
According to rc-table docs you can use expandIconColumnIndex for the index column you want to add the +, also you have to add expandIconAsCell={false} to make it render as part of the cell.
See Demo
This is how you can make any column expendable.
First add expandedRowKeys in your component state
state = {
expandedRowKeys: [],
};
Then you need to add these two functions onExpand and updateExpandedRowKeys
<Table
id="table-container"
rowKey={record => record.rowKey}
className={styles['quote-summary-table']}
pagination={false}
onExpand={this.onExpand}
expandedRowKeys={this.state.expandedRowKeys}
columns={columns({
updateExpandedRowKeys: this.updateExpandedRowKeys,
})
}
dataSource={this.data}
oldTable={false}
/>
This is how you need to define the function so
that in expandedRowKeys we will always have
updates values of expanded rowKeys
onExpand = (expanded, record) => {
this.updateExpandedRowKeys({ record });
};
updateExpandedRowKeys = ({ record }) => {
const rowKey = record.rowKey;
const isExpanded = this.state.expandedRowKeys.find(key => key === rowKey);
let expandedRowKeys = [];
if (isExpanded) {
expandedRowKeys = expandedRowKeys.reduce((acc, key) => {
if (key !== rowKey) acc.push(key);
return acc;
}, []);
} else {
expandedRowKeys.push(rowKey);
}
this.setState({
expandedRowKeys,
});
}
And finally, you need to call the function updateExpandedRowKeys
for whichever column you want to have the expand-collapse functionality available.
Even it can be implemented for multiple columns.
export const columns = ({
updateExpandedRowKeys,
}) => {
let columnArr = [
{
title: 'Product',
key: 'productDes',
dataIndex: 'productDes',
className: 'productDes',
render: (text, record) => (
<span onClick={rowKey => updateExpandedRowKeys({ record })}>
{text}
</span>
),
}, {
title: 'Product Cat',
key: 'productCat',
dataIndex: 'productCat',
className: 'product-Cat',
}]
}