How to change id of tanstack React Table useSelectRow - reactjs

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

Related

React table - checkbox showing button to take to a new page

I have a table I have built using react Table. I have a check box in my fist column. When you click the check box I want a button to appear new to it to take you to a new page.
How would I achieve this?
My code for the check box in the table is as follows:
const columns = React.useMemo(
() => [
{
Header: '',
accessor: 'checked',
Cell: () => {
return (
<div>
<input type="checkbox" />
</div>
);
},
},
The particle path I want to go to is called /individual-user. Can anyone assist?

enableRowSelection in useTable

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,
])
}
)

Material Table : Custom Column Filter, unable to filter based on value selection

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

Delete particular item in React Table?

Header: "Delete",
id:'delete',
accessor: str => "delete",
Cell: (row)=> (
<span onClick={(row) => this.onRemoveHandler(row,props)} style={{cursor:'pointer',color:'blue',textDecoration:'underline'}}>
Delete
</span>
)
React Table
This is related to the header delete span link.The code snippets shows the render the delete label with hyperlink.
Here once a user click on delete link how can I get the id of that particular row.
ID has been already assgined to all the row from the json data.
So,How to pass the cellInfo or rowInfo inside the onClick function .
If you check out the docs (specificaly under 'Renderers'), the row object the cell receives is in the following format:
{
// Row-level props
row: Object, // the materialized row of data
original: , // the original row of data
index: '', // the index of the row in the original array
viewIndex: '', // the index of the row relative to the current view
level: '', // the nesting level of this row
nestingPath: '', // the nesting path of this row
aggregated: '', // true if this row's values were aggregated
groupedByPivot: '', // true if this row was produced by a pivot
subRows: '', // any sub rows defined by the `subRowKey` prop
// Cells-level props
isExpanded: '', // true if this row is expanded
value: '', // the materialized value of this cell
resized: '', // the resize information for this cell's column
show: '', // true if the column is visible
width: '', // the resolved width of this cell
maxWidth: '', // the resolved maxWidth of this cell
tdProps: '', // the resolved tdProps from `getTdProps` for this cell
columnProps: '', // the resolved column props from 'getProps' for this cell's column
classes: '', // the resolved array of classes for this cell
styles: '' // the resolved styles for this cell
}
Depending on what your input data looks like, you can use this information to delete from the dataset. If you plan on dynamically editing your data, you should store it in the state, so that the table component can update according to your edits. Assuming that in your state, you save your dataset as data, and use that to populate the table, you can alter the state in your onclick function:
Header: "Delete",
id:'delete',
accessor: str => "delete",
Cell: (row)=> (
<span onClick={() => {
let data = this.state.data;
console.log(this.state.data[row.index]);
data.splice(row.index, 1)
this.setState({data})
}}>
Delete
</span>
)
so a rough approximation of your app would like this:
this.state = {
data: <your data set>
}
<ReactTable
data={this.state.data}
columns={[
<other columns you have>,
{
Header: "Delete",
id:'delete',
accessor: str => "delete",
Cell: (row)=> (
<span style={{cursor:'pointer',color:'blue',textDecoration:'underline'}}
onClick={() => {
let data = this.state.data;
console.log(this.state.data[row.index]);
data.splice(row.index, 1)
this.setState({data})
}}>
Delete
</span>
)}
]}
/>
And of course, you don't need to log that row to the console, that doesn't need to be there. This is also just the quickest and easiest way to handle it, you could instead use the row object to get any specific element you want (id, name, etc.) and use that to remove from the dataset
An important note though: There is a big difference between viewIndex and index, index is what you want to use for your specific case
If you are like me and are using React-Table v7 and you are also using a hooks based approach in your components you will want to do it this way.
const [data, setData] = useState([]);
const columns = React.useMemo(
() => [
{
Header: 'Header1',
accessor: 'Header1Accessor',
},
{
Header: 'Header2',
accessor: 'Header2Accessor',
},
{
Header: 'Delete',
id: 'delete',
accessor: (str) => 'delete',
Cell: (tableProps) => (
<span style={{cursor:'pointer',color:'blue',textDecoration:'underline'}}
onClick={() => {
// ES6 Syntax use the rvalue if your data is an array.
const dataCopy = [...data];
// It should not matter what you name tableProps. It made the most sense to me.
dataCopy.splice(tableProps.row.index, 1);
setData(dataCopy);
}}>
Delete
</span>
),
},
],
[data],
);
// Name of your table component
<ReactTable
data={data}
columns={columns}
/>
The important part is when you are defining your columns make sure that the data in your parent component state is part of the dependency array in React.useMemo.

Antd: Is it possible to move the table row expander inside one of the cells?

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',
}]
}

Resources