Virtualized Table + Resizeable Columns #2607
Unanswered
wildcat-cs
asked this question in
General
Replies: 1 comment 1 reply
-
Here's an example comp: import React from 'react'
import styled from 'styled-components'
import { useTable, useBlockLayout, useResizeColumns, useGlobalFilter } from 'react-table'
import { FixedSizeList } from 'react-window'
export interface TableProps {
columns: any,
data: any
}
export interface TableStylesProps {
setMargin: boolean
}
const TableStyles = styled.div<TableStylesProps>`
.table {
display: inline-block;
border-spacing: 0;
border: 1px solid black;
.tr {
:last-child {
.td {
border-bottom: 0;
}
}
}
.th {
font-weight: bold;
:last-child {
margin-right: ${props => props.setMargin ? '5px' : 0};
}
}
.th,
.td {
margin: 0;
padding: 0.5rem;
border-bottom: 1px solid black;
border-right: 1px solid black;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
${'' /* In this example we use an absolutely position resizer,
so this is required. */}
position: relative;
:last-child {
:first-child {
border-right: 0;
}
}
.resizer {
display: inline-block;
background: blue;
width: 5px;
height: 100%;
position: absolute;
right: 0;
top: 0;
transform: translateX(50%);
z-index: 1;
${'' /* prevents from scrolling while dragging on touch devices */}
touch-action:none;
&.isResizing {
background: red;
}
}
}
}
`
function GlobalFilter({
preGlobalFilteredRows, globalFilter, setGlobalFilter, totalColumnsWidth
}: {
preGlobalFilteredRows: any,
globalFilter: any,
setGlobalFilter: any,
totalColumnsWidth: any
}) {
const count = preGlobalFilteredRows.length
return (
<span>
<input
value={globalFilter || ""}
onChange={e => {
setGlobalFilter(e.target.value || undefined); // Set undefined to remove the filter entirely
}}
placeholder={`🔍Search ${count} records...`}
style={{
fontSize: '1rem',
border: '0',
backgroundColor: '#FAFAFA',
outlineWidth: 0,
fontWeight: 300,
width: totalColumnsWidth - 16
}}
/>
</span>
)
}
export default function DPTable(props: TableProps) {
const { data, columns } = props
const defaultColumn = React.useMemo(
() => ({
minWidth: 30,
width: 150,
}),
[]
)
const [tableHeight, setTableHeight] = React.useState(700)
React.useEffect(() => {
setTableHeight(window.innerHeight - 270)
window.addEventListener('resize', updateHeightCallback);
return () => {
window.removeEventListener('resize', updateHeightCallback);
}
}, [])
const updateHeightCallback = () => {
setTableHeight(window.innerHeight - 270)
}
// @ts-ignore
const { getTableProps, getTableBodyProps, headerGroups, totalColumnsWidth, rows, prepareRow, state: { globalFilter }, setGlobalFilter, preGlobalFilteredRows } = useTable(
{
columns,
data,
defaultColumn,
},
useBlockLayout,
useResizeColumns,
useGlobalFilter
)
const RenderRow = React.useCallback(
({ index, style }) => {
const row = rows[index]
prepareRow(row)
return (
<div
{...row.getRowProps({
style,
})}
className="tr"
>
{row.cells.map(cell => {
return (
<div {...cell.getCellProps()} className="td" title={cell.value}>
{cell.render('Cell')}
</div>
)
})}
</div>
)
},
[prepareRow, rows]
)
return (
<TableStyles setMargin={tableHeight < (rows.length * 35)}>
<div {...getTableProps()} className="table">
<div className="thead">
<div className="tr">
<div className="th"
style={{
textAlign: 'left',
}}
>
<GlobalFilter
preGlobalFilteredRows={preGlobalFilteredRows}
globalFilter={globalFilter}
setGlobalFilter={setGlobalFilter}
totalColumnsWidth={totalColumnsWidth}
/>
</div>
</div>
{headerGroups.map((headerGroup: any) => (
<div {...headerGroup.getHeaderGroupProps()} className="tr">
{headerGroup.headers.map((column: any) => (
<div {...column.getHeaderProps()} className="th">
{column.render('Header')}
{/* Use column.getResizerProps to hook up the events correctly */}
<div
{...column.getResizerProps()}
className={`resizer ${column.isResizing ? 'isResizing' : ''}`}
/>
</div>
))}
</div>
))}
</div>
<div {...getTableBodyProps()} className="mostly-customized-scrollbar">
<FixedSizeList
height={rows.length > 20 ? tableHeight : rows.length * 35}
itemCount={rows.length}
itemSize={35}
width={totalColumnsWidth}
>
{RenderRow}
</FixedSizeList>
</div>
</div>
</TableStyles>
)
} I am too lazy to create a code sandbox 😓 If you still facing problems I will create one. |
Beta Was this translation helpful? Give feedback.
1 reply
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Has anyone successfully created a table with the combination of react-window and useResizeColumns?
This issue I am trying to figure out is when the row changes height due to text wrapping from the column being resized by the user. This causes the rows to overlap (or causes gaps) due to react-window's absolute positioning of the rows. react-window does have an API to invalidate it's cached row heights but not sure if this is a good route to go with every movement of the mouse when resizing.
Beta Was this translation helpful? Give feedback.
All reactions