- Sponsor
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(useGridLayout): Support header groups #3542
Conversation
Someone is attempting to deploy a commit to the Tanstack Team on Vercel. A member of the Team first needs to authorize it. |
Column // getTableProps
const width = typeof column.width === 'number' ? `${column.width}px` : column.width
const maxWidth = typeof column.maxWidth === 'number' ? `${column.maxWidth}px` : column.maxWidth
return `minmax(${width},${maxWidth})`
// instead of
if (typeof column.width === 'number') return `${column.width}px`
return column.width However, I'm not sure if we could support both minWidth and maxWidth at the same time. There doesn't appear to be something like |
Adapted Examples(since there aren't any examples with Column Resizing Exampleconst Styles = styled.div`
padding: 1rem;
.table {
display: inline-block;
border-spacing: 0;
border: 1px solid black;
.th,
.td {
margin: 0;
padding: 0.5rem;
border-bottom: 1px solid black;
border-right: 1px solid black;
${'' /* One way to deal with borders in the useGridLayout table
is to use nth-child pseudo-selectors. */}
:nth-child(6n + 8) {
border-right: 0;
}
:nth-child(6n + 8):nth-last-child(-n + 7) ~ * {
border-bottom: 0;
}
.resizer {
display: inline-block;
background: blue;
width: 10px;
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 Table({ columns, data }) {
const defaultColumn = React.useMemo(
() => ({
minWidth: 30,
width: 'auto',
maxWidth: 400,
}),
[]
)
const {
getTableProps,
headerGroups,
rows,
prepareRow,
state,
resetResizing,
} = useTable(
{
columns,
data,
defaultColumn,
},
useGridLayout,
useResizeColumns
)
return (
<>
<button onClick={resetResizing}>Reset Resizing</button>
<div>
<div {...getTableProps()} className="table">
{headerGroups.map(headerGroup =>
headerGroup.headers.map(column => (
<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>
))
)}
{rows.map((row, i) => {
prepareRow(row)
return row.cells.map(cell => {
return (
<div {...cell.getCellProps()} className="td">
{cell.render('Cell')}
</div>
)
})
})}
</div>
</div>
<pre>
<code>{JSON.stringify(state, null, 2)}</code>
</pre>
</>
)
} Expanding Exampleconst Styles = styled.div`
padding: 1rem;
table {
border-spacing: 0;
border: 1px solid black;
${'' /* One way to deal with borders in the useGridLayout table
is to use grid-gap and background. */}
background-color: black;
grid-gap: 1px;
> * {
background-color: white;
}
th,
td {
margin: 0;
padding: 0.5rem;
}
}
`
function Table({ columns: userColumns, data }) {
const {
getTableProps,
headerGroups,
rows,
prepareRow,
state: { expanded },
} = useTable(
{
columns: userColumns,
data,
},
useExpanded, // Use the useExpanded plugin hook
useGridLayout
)
return (
<>
<table {...getTableProps()}>
{headerGroups.map(headerGroup =>
headerGroup.headers.map(column => (
<th {...column.getHeaderProps()}>{column.render('Header')}</th>
))
)}
{rows.map((row, i) => {
prepareRow(row)
return row.cells.map(cell => {
return <td {...cell.getCellProps()}>{cell.render('Cell')}</td>
})
})}
</table>
<br />
<div>Showing the first 20 results of {rows.length} rows</div>
<pre>
<code>{JSON.stringify({ expanded: expanded }, null, 2)}</code>
</pre>
</>
)
} Sub-Components Exampleconst Styles = styled.div`
padding: 1rem;
.table {
border-spacing: 0;
border: 1px solid black;
${'' /* One way to deal with borders in the useGridLayout table
is to use grid-gap and background. */}
background-color: black;
grid-gap: 1px;
> * {
background-color: white;
}
> div {
margin: 0;
padding: 0.5rem;
}
}
`
// A simple way to support a renderRowSubComponent is to make a render prop
// This is NOT part of the React Table API, it's merely a rendering
// option we are creating for ourselves in our table renderer
function Table({ columns: userColumns, data, renderRowSubComponent }) {
const {
getTableProps,
headerGroups,
rows,
prepareRow,
state: { expanded },
} = useTable(
{
columns: userColumns,
data,
},
useExpanded, // We can useExpanded to track the expanded state
// for sub components too!
useGridLayout
)
return (
<>
<pre>
<code>{JSON.stringify({ expanded: expanded }, null, 2)}</code>
</pre>
<div className="table" {...getTableProps()}>
{headerGroups.map(headerGroup =>
headerGroup.headers.map(column => (
<div {...column.getHeaderProps()}>
{column.render('Header')}
</div>
))
)}
{rows.map((row, i) => {
prepareRow(row)
return (
<>
{row.cells.map(cell => {
return <div {...cell.getCellProps()}>{cell.render('Cell')}</div>
})}
{/*
If the row is in an expanded state, render a row with a
column that fills the entire length of the table.
*/}
{row.isExpanded ? (
<div {...row.getRowProps()}>
{/*
Inside it, call our renderRowSubComponent function. In reality,
you could pass whatever you want as props to
a component like this, including the entire
table instance. But for this example, we'll just
pass the row
*/}
{renderRowSubComponent({ row })}
</div>
) : null}
</>
)
})}
</div>
<br />
<div>Showing the first 20 results of {rows.length} rows</div>
</>
)
} |
This pull request is being marked as stale (no activity in the last 14 days) |
This pull request has been detected as stale (no activity in the last 14 days) and automatically closed. It's very likely that your pull request has remained here this long because it introduces breaking changes to the v7 API. React Table v8 is currently in alpha (soon beta!) and already contains bug fixes, performance improvements and architectural changes that likely address the issue this pull request is meant to solve.
|
Was this closed by mistake? |
@tannerlinsley This PR is for v7 and makes It's unclear to me if updates will still be made to v7 going forward, but I can open a new PR to the v7 branch if you think this is worthwhile. |
Reopened |
Header Groups Bug
Resolves #3537
useGridLayout
could not display header groups by default. This seemed like a bug as it is fairly common functionality that it should be able to handle.Header groups can be supported with the grid layout by using the css grid-column property with a span of the column's
totalVisibleHeaderCount
.Column Resizing Bug
useGridLayout
has a bug that comes from 'auto' or 'fr' units. When some resizing columns, the cursor doesn't stay with the resizer handle because 'auto' width columns rescale based on the column being resized. e.g. columnResizing state thinks the column width is 150, but it is actually 200 because of grid 'auto' resizing.This column resizing bug was fixed by locking the width of all columns not being resized. Now, while resizing, this behaves exactly like the Resizing example (with
useBlockLayout
). After resizing, all columns that have not been resized will default back to their previous value. As a bonus, this supports user-provided 'width' values on columns. If 'auto' width columns is desired (instead of the default 150), that can be set with the defaultColumn useTable prop.useGridLayout
also had a bug where columns could be resized beyond the minWidth and maxWidth values. These values are now taken into account when resizing. However, this MR does not apply minWidth and maxWidth during initial column sizing.