Skip to content
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

feat(Table): add support for fillHeight on <Table> #330

Merged
merged 4 commits into from Apr 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
81 changes: 41 additions & 40 deletions README.md

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions docs/index.tsx
Expand Up @@ -73,6 +73,10 @@ function App() {
title: 'Automatic height',
content: require('./md/AutoHeightTable.md')
},
{
title: 'Fill height',
content: require('./md/FillHeightTable.md')
},

{
title: 'Affix Header',
Expand Down
84 changes: 84 additions & 0 deletions docs/md/FillHeightTable.md
@@ -0,0 +1,84 @@
### Fill height

<!--start-code-->

```js
const App = () => {
const [height, setheight] = React.useState(30);
const handleChange = event => {
const value = parseInt(event.target.value);
setheight(value);
};

const data = fakeData.filter((item, index) => index < 50);
return (
<div>
container height: <input type="text" onChange={handleChange} value={height} /> rem
<hr />
<div style={{ border: '1px solid red', height: `${height}rem` }}>
<Table
height={400}
fillHeight
data={data}
onRowClick={data => {
console.log(data);
}}
>
<Column width={70} align="center">
<HeaderCell>Id</HeaderCell>
<Cell dataKey="id" />
</Column>

<Column width={130}>
<HeaderCell>First Name</HeaderCell>
<Cell dataKey="firstName" />
</Column>

<Column width={130}>
<HeaderCell>Last Name</HeaderCell>
<Cell dataKey="lastName" />
</Column>

<Column width={200}>
<HeaderCell>City</HeaderCell>
<Cell dataKey="city" />
</Column>

<Column width={200}>
<HeaderCell>Street</HeaderCell>
<Cell dataKey="street" />
</Column>

<Column width={200}>
<HeaderCell>Company Name</HeaderCell>
<Cell dataKey="companyName" />
</Column>

<Column width={200}>
<HeaderCell>Email</HeaderCell>
<Cell dataKey="email" />
</Column>

<Column width={200}>
<HeaderCell>Email</HeaderCell>
<Cell dataKey="email" />
</Column>

<Column width={200}>
<HeaderCell>Email</HeaderCell>
<Cell dataKey="email" />
</Column>

<Column width={200}>
<HeaderCell>Email</HeaderCell>
<Cell dataKey="email" />
</Column>
</Table>
</div>
</div>
);
};
ReactDOM.render(<App />);
```

<!--end-code-->
33 changes: 19 additions & 14 deletions src/Table.tsx
Expand Up @@ -44,7 +44,6 @@ import type {
RowKeyType,
TableLocaleType
} from './@types/common';

/**
* Filter those expanded nodes.
* @param data
Expand All @@ -67,9 +66,18 @@ const filterTreeData = (data: any[], expandedRowKeys: RowKeyType[], rowKey?: Row
};

export interface TableProps extends Omit<StandardProps, 'onScroll'> {
/** Automatic Height */
/**
* The height of the table will be automatically expanded according to the number of data rows,
* and no vertical scroll bar will appear
* */
autoHeight?: boolean;

/**
* Force the height of the table to be equal to the height of its parent container.
* Cannot be used together with autoHeight.
*/
fillHeight?: boolean;

/** Affix the table header to the specified position on the page */
affixHeader?: boolean | number;

Expand All @@ -95,7 +103,7 @@ export interface TableProps extends Omit<StandardProps, 'onScroll'> {
defaultExpandedRowKeys?: RowKeyType[];

/** Table data */
data: RowDataType[];
data?: RowDataType[];

/** Specify the default expanded row by rowkey (Controlled) */
expandedRowKeys?: RowKeyType[];
Expand Down Expand Up @@ -269,6 +277,7 @@ const Table = React.forwardRef((props: TableProps, ref) => {
minHeight = 0,
height = 200,
autoHeight,
fillHeight,
rtl: rtlProp,
translate3d = true,
rowKey,
Expand Down Expand Up @@ -377,7 +386,8 @@ const Table = React.forwardRef((props: TableProps, ref) => {
tableOffset,
headerOffset,
setScrollY,
setScrollX
setScrollX,
getTableHeight
} = useTableDimension({
data: dataProp,
width: widthProp,
Expand All @@ -389,7 +399,9 @@ const Table = React.forwardRef((props: TableProps, ref) => {
affixHorizontalScrollbar,
headerHeight,
height,
minHeight,
autoHeight,
fillHeight,
children,
expandedRowKeys,
onTableScroll: (coords: { x?: number; y?: number }) => {
Expand All @@ -406,16 +418,8 @@ const Table = React.forwardRef((props: TableProps, ref) => {
}
});

const getTableHeight = useCallback(() => {
if (data.length === 0 && autoHeight) {
return height;
}

return autoHeight ? Math.max(headerHeight + contentHeight.current, minHeight) : height;
}, [autoHeight, contentHeight, data.length, headerHeight, height, minHeight]);

useAffix({
tableHeight: getTableHeight,
getTableHeight,
contentHeight,
affixHorizontalScrollbar,
affixHeader,
Expand Down Expand Up @@ -1049,14 +1053,15 @@ const Table = React.forwardRef((props: TableProps, ref) => {
Table.displayName = 'Table';
Table.propTypes = {
autoHeight: PropTypes.bool,
fillHeight: PropTypes.bool,
affixHeader: PropTypes.oneOfType([PropTypes.bool, PropTypes.number]),
affixHorizontalScrollbar: PropTypes.oneOfType([PropTypes.bool, PropTypes.number]),
bordered: PropTypes.bool,
className: PropTypes.string,
classPrefix: PropTypes.string,
children: PropTypes.any,
cellBordered: PropTypes.bool,
data: PropTypes.array.isRequired,
data: PropTypes.array,
defaultExpandAllRows: PropTypes.bool,
defaultExpandedRowKeys: PropTypes.array,
defaultSortType: PropTypes.any,
Expand Down
10 changes: 5 additions & 5 deletions src/utils/useAffix.ts
Expand Up @@ -10,7 +10,7 @@ import type { ListenerCallback, ElementOffset } from '../@types/common';
import type { ScrollbarInstance } from '../Scrollbar';

interface AffixProps {
tableHeight: () => number;
getTableHeight: () => number;
contentHeight: React.MutableRefObject<number>;
affixHeader?: boolean | number;
affixHorizontalScrollbar?: boolean | number;
Expand All @@ -23,7 +23,7 @@ interface AffixProps {

const useAffix = (props: AffixProps) => {
const {
tableHeight,
getTableHeight,
contentHeight,
affixHorizontalScrollbar,
affixHeader,
Expand All @@ -38,7 +38,7 @@ const useAffix = (props: AffixProps) => {
const handleAffixHorizontalScrollbar = useCallback(() => {
const scrollY = window.scrollY || window.pageYOffset;
const windowHeight = getHeight(window);
const height = tableHeight();
const height = getTableHeight();

const bottom = typeof affixHorizontalScrollbar === 'number' ? affixHorizontalScrollbar : 0;
const offsetTop = tableOffset.current?.top || 0;
Expand All @@ -56,7 +56,7 @@ const useAffix = (props: AffixProps) => {
removeStyle(scrollbarXRef.current.root, 'bottom');
}
}
}, [affixHorizontalScrollbar, headerHeight, scrollbarXRef, tableHeight, tableOffset]);
}, [affixHorizontalScrollbar, headerHeight, scrollbarXRef, getTableHeight, tableOffset]);

const handleAffixTableHeader = useCallback(() => {
const top = typeof affixHeader === 'number' ? affixHeader : 0;
Expand Down Expand Up @@ -88,7 +88,7 @@ const useAffix = (props: AffixProps) => {
* Update the position of the fixed element after the height of the table changes.
* fix: https://github.com/rsuite/rsuite/issues/1716
*/
useUpdateEffect(handleWindowScroll, [tableHeight]);
useUpdateEffect(handleWindowScroll, [getTableHeight]);

useEffect(() => {
if (isNumberOrTrue(affixHeader) || isNumberOrTrue(affixHorizontalScrollbar)) {
Expand Down
1 change: 1 addition & 0 deletions src/utils/useScrollListener.ts
Expand Up @@ -406,6 +406,7 @@ const useScrollListener = (props: ScrollListenerProps) => {

const onScrollTop = (top = 0) => {
const [nextScrollY, handleScrollY] = getControlledScrollTopValue(top);
const height = getTableHeight();

setScrollY(nextScrollY);
scrollbarYRef?.current?.resetScrollBarPosition?.(handleScrollY);
Expand Down