React Table responsive hidden columns - reactjs

I'm trying to find a way to hide a few columns based on the window size using react-table.
I've gotten as far as using a custom hook to return the window size, then based on those size's to return an array with the column accessor id's
const { width } = useWindowDimensions();
const [cols, setCols] = useState([""]);
.
.
. useEffect(() => {
console.log("cols", cols);
if (width < 1000) {
setCols(["id", "osName"]);
} else {
setCols(["id"]);
}
}, [width, setCols]);
.
.
. <ComputerTable
hiddenColumns={cols}
columns={columns}
data={...}
};
})}
/>
this passes through my Table component and is loaded on
useTable(
.
.
.
initialState: { pageIndex: 0, hiddenColumns: hiddenColumns || [] },
.
.
)
This works on the initial page render, however when the window resizes it does not update.
cols does appear to be updating on the fly within the component code when I console.log it, but in the view itself, the table does not re-render based on that array update.
Can I accomplish this with my logic, or is there a better way to accomplish this?

initialState: { pageIndex: 0, hiddenColumns: hiddenColumns || [] }, is an initial state, not an updating one. You will need to engineer things so you can say:
colsToHide.forEach(c => c.toggleHidden(true))
// OR
colsToHide.forEach(c => c.toggleHidden(c.isVisible)) // to toggle state
// OF
colsToHide.forEach(c => c.toggleHidden(state.blah)) // for if you setup some state
Use an useEffect() to perform state setup as required, and in the return (...) for rendering the table.
I am about to write up what I did in a new post to answer how to hide columns NOT using
<IndeterminateCheckbox {...getToggleHideAllColumnsProps()}/>
which I could only find answers for.
See React-table hide various columns from button click

Related

Conditional styling on row for dynamic cell value

Conditional row styling on ag grid where I want to do rowstyle on user choice of cell value
gridoptions.getRowStyle = function(params) {
if (params.node.data === 'cell value typed by user in external/custom component i.e outside grid') {
return { 'background': value selected by user in cutom componet outside grid };
}
}
#sandeep's answer works perfectly. I just want to chime in another way to solve the problem which is to use context. context is just another javascript object which contains any information that you want to share within AgGrid. The data will be accessible in most AgGrid callbacks for example cell renderers, editors's render callback and in your case getRowStyle callback
const sickDays = // data from external component
const color = // data from external component
<AgGridReact
getRowStyle={(params) => {
const { styles, data } = params.context;
if (params.node.data["sickDays"] === data.sickDays) {
return { backgroundColor: styles.color };
}
return null;
}}
context={{
data: { sickDays },
styles: { color }
}}
/>
Live Demo
here is a plunkr which should give you idea to solve the problem. since i don't know much about your component hence i used two input boxes with button to set background color to row but you can use complex styles as well.
I am using api.redrawRows() since the operation we are performing needs to work on row.

React Table using hooks expand and collapse rows

I am using react-table component inside my project. The row expansion property is something that my features utilized and it is working fine now.
I need the ability to collapse all the rows while I expand a row. ie Only one row should be open at a time. I did go through many documentation and stackoverflow links but none didn't work out. Please note that this implementation is using hooks. Just like the one mentioned here : https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/expanding
By default they allow to open more than one row at a time, but I need to implement the opposite.
The closest I came to is this : Auto expandable rows and subrows react table using hooks
But here its opening on initial load.
Thanks
I have only added a portion of App function here. Codesandbox: https://codesandbox.io/s/jolly-payne-dxs1d?fontsize=14&hidenavigation=1&theme=dark.
Note: I am not used to react-table library. This code is a sample that only works in the table with two levels of rows. You can optimize the code with recursion or some other way to make the code work in multi-level tables.
Cell: ({ row, rows, toggleRowExpanded }) =>
// Use the row.canExpand and row.getToggleRowExpandedProps prop getter
// to build the toggle for expanding a row
row.canExpand ? (
<span
{...row.getToggleRowExpandedProps({
style: {
// We can even use the row.depth property
// and paddingLeft to indicate the depth
// of the row
paddingLeft: `${row.depth * 2}rem`
},
onClick: () => {
const expandedRow = rows.find(row => row.isExpanded);
if (expandedRow) {
const isSubItemOfRow = Boolean(
expandedRow && row.id.split(".")[0] === expandedRow.id
);
if (isSubItemOfRow) {
const expandedSubItem = expandedRow.subRows.find(
subRow => subRow.isExpanded
);
if (expandedSubItem) {
const isClickedOnExpandedSubItem =
expandedSubItem.id === row.id;
if (!isClickedOnExpandedSubItem) {
toggleRowExpanded(expandedSubItem.id, false);
}
}
} else {
toggleRowExpanded(expandedRow.id, false);
}
}
row.toggleRowExpanded();
}
})}
>
{row.isExpanded ? "👇" : "👉"}
</span>
) : null

Getting current table data from Ant Design Table

I'm using Ant design table for displaying some data. New data arrives every one second. When user clicks on button, I need to export current table data to XSL.
I'm getting current data in this way:
onChange={(pagination, filter, sorter, currentTable) => this.onTableChange(filter, sorter, currentTable)}.
This thing works and gets me good and filtered data, but when I get new data, I can't get those new data because this function is not triggered while none of the filters or sort settings didn't change. Is there any way to get current table data without dummy changing filter to trigger onChange function?
Title and footer return only current page data.
Code show here
{ <Table
dataSource={this.props.data}
rowKey={(record) => { return record.id}}
columns={this.state.Columns}
pagination={this.state.pageSizeOptions}
rowClassName={(record) => { return
this.getRowClassNames(record) }}
expandedRowKeys={ this.state.expandedRowKeys }
expandedRowRender={record => { return
this.getEventsRows(record) }}
onExpand={(expanded, record) => {
this.onExpandRow(expanded, record.id) }}
expandRowByClick={false}
onChange={(pagination, filter, sorter, currentTable)
=> this.onTableChange(filter, sorter, currentTable)}
/>
}
You can store pagination, sorter and filter data in your component state. Also you can pass these params to your redux state and store there. If you can share your code, i can provide more specific answers.
Below you can find my solution for permanent filter. I was sending filter params to API and get filtered data. If you want to filter it in the component, you can use component lifecycle or render method.
onTableChange(pagination, filter, sorter){
const { params, columns } = this.state;
/** You can do any custom thing you want here. Below i update sort type in my state and pass it to my redux function */
if(sorter.order != null)
params.ordering = (sorter.order === 'descend' ? "-" : "")+ sorter.columnKey.toString();
this.setState({params});
this.props.listUsers(this.state.params);
}
This is because you have taken either columns, datasource varibale as object instead of array.
write
this.state.someVariable=[]
instead of
this.state.someVariable = {}

How to fix pagination reset issue in react-table?

I am working for a feature where i have to apply a filter outside the component which is using react-table, but the current page number doesn't get reset after the filter is being applied. The result being fetched (have applied server-side pagination) shows the first page's data.
I have tried to use the callback onFetchData to change the current page number but it does'nt get triggered when the filter from outside the component is applied.
render() {
const { orders, onUpdate } = this.props;
const defaultPageSize = 50;
return (
<div className="admin-report-table">
<ReactTable
data={orders.ordersData}
columns={this.columns}
pages={Math.ceil(orders.count / defaultPageSize)}
defaultPageSize={defaultPageSize}
multiSort={false}
showPageSizeOptions={false}
showPaginationTop
className="-striped -highlight"
noDataText="No orders found. Please check your connection or change your filters."
filterable
manual // informs React Table that you'll be handling sorting and pagination server-side
onFetchData={(state) => {
const { page, pageSize, filtered, sorted } = state;
const adjustedPage = page + 1; // since library page starts from 0
onUpdate({
page: adjustedPage,
filtered,
pageSize,
sorted,
});
}}
/>
</div>
);
}
The Page number should be reset to 1 e.g. current display is Page 2 of 3, after the filter from outside the table is applied, the result is fetched and shown but the Page 2 of 3 doesn't change while the result in the table is of page 1.
Set autoResetPage: false
https://react-table.tanstack.com/docs/api/usePagination#table-options
its gonna avoid rendering all the time.
I had the same issue in my react table, in the solution for that, in the componentWillReceiveProps method I update the page props of the react-table and set it to the "0" when react-table gets new filtered data (Props changed ), its work for me fine, so in your code just set page props as 0 when your table get new data from the parent
componentWillReceiveProps(nextProps: Readonly<IProps>): void {
if (nextProps.properties !== this.props.properties && nextProps.properties.length > 0) {
this.setState({
selectedPageNumber : 0
})
}
}
This issue could be solved by the hacky solution found here: TroyWolf's solution.
And read the whole post there - it may be that your current case is in another comment. If the post will be removed somehow I post it here:
store a reference to the ReactTable's instance. It works to directly update myReactTableInstance.state.page = 0
With similar use cases, I have found its best to use once's own controlled page state for index, as mentioned here:
Check here as mentioned in the docs
It becomes simpler to handle the page reset actions on custom filtering/custom sorting, and trigger accordingly
I am using react table's out of the box pagination and the issue I had was how to extract the current pageIndex from react table. Because every time there was an action on the row of React table, that did not alter the no. of rows, the React table would go back to page 0.
Following worked for me, hacky but works -
On parent component calling React table -
signalTableData is where I have my data for columns and datarows. this could be your data.
const [pageIndex, setPageIndex] = useState(0);
<ReactTable
columns={signalTableData ? signalTableData.headerRow : <div>Loading...</div>}
data={signalTableData.dataRows ? signalTableData.dataRows : <div>Loading...</div>}
sortbyCollumn='originDate'
desc={true}
pageIndex = {pageIndex}
setPageIndex = {setPageIndex}
/>
One React Table js -
function Table({ columns, data, sortbyCollumn, desc, pageIndex, setPageIndex }) {...
and
useTable(
{
columns,
data,
defaultColumn, // Be sure to pass the defaultColumn option
filterTypes,
autoResetPage: false,
initialState: {
pageSize: 5,
pageIndex: pageIndex,
sortBy: [
{
id: sortbyCollumn,
desc: desc
}
] },
},

How to rerender entire single row in react-table?

I have a react-table component in my app and pass there next props:
<ReactTable
data={this.props.words}
columns={columns}
getTrProps={changing_state_func}
/>
changing_state_func is a function that changes state of the component that wraps react-table. Specifically, this function fills an array that contains ids of the data objects for rows. So I'd like to highlight the rows with the data for those ids... Cannot figure it out how to do it with this particular datagrid. Maybe somebody has the experience working with react-table and example on this case.
I'm not sure what actually you're trying to do, but here are my thoughts.
getTrProps is used to pass props to the table's rows.
So according the module docs, you can pass whatever you want.
The example shows how you can change the color of the rows, those meet specific condition:
// Any Tr element will be green if its (row.age > 20)
<ReactTable
getTrProps={(state, rowInfo, column) => {
return {
style: {
background: rowInfo.age > 20 ? 'green' : 'red'
}
}
}}
/>
Fixes to the react-table 5.0.2 allow to have access to the table's instance, and the problem can be solved by calling .forceUpdate() method on the table's instance. changing_state_func in this case may look like this:
changing_state_func = (state, rowInfo, column, instance) => {
if (!rowInfo) return {}
return {
style: {
background: (this.state.rowsIdsArray.includes(rowInfo.row.id)) ? 'green' : null
},
onClick: () => {
this.setState({rowsIdsArray: this.state.rowsIdsArray.concat([rowInfo.row.id])});
instance.forceUpdate()
}
}
}
Thanks to the Tanner Linsley for responsiveness and quick fixes.

Resources