Skip to content

Commit ef32375

Browse files
authored
feat(AnalyticalTable): add AnalyticalTableVisibleRowCountMode.AutoWithEmptyRows (#5347)
Closes #5341
1 parent ce0f63d commit ef32375

File tree

8 files changed

+133
-62
lines changed

8 files changed

+133
-62
lines changed

packages/main/src/components/AnalyticalTable/AnalyticalTable.cy.tsx

Lines changed: 66 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { cssVarToRgb, cypressPassThroughTestsFactory } from '@/cypress/support/utils';
12
import { ThemingParameters } from '@ui5/webcomponents-react-base';
23
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
34
import type { AnalyticalTableDomRef, AnalyticalTablePropTypes } from '../..';
@@ -7,13 +8,13 @@ import {
78
AnalyticalTableScaleWidthMode,
89
AnalyticalTableSelectionBehavior,
910
AnalyticalTableSubComponentsBehavior,
11+
AnalyticalTableVisibleRowCountMode,
1012
Button,
1113
Input
1214
} from '../..';
1315
import { AnalyticalTableSelectionMode, AnalyticalTableVisibleRowCountMode, ValueState } from '../../enums/index.js';
1416
import { useManualRowSelect } from './pluginHooks/useManualRowSelect';
1517
import { useRowDisableSelection } from './pluginHooks/useRowDisableSelection';
16-
import { cssVarToRgb, cypressPassThroughTestsFactory } from '@/cypress/support/utils';
1718

1819
const generateMoreData = (count) => {
1920
return new Array(count).fill('').map((item, index) => ({
@@ -124,54 +125,76 @@ describe('AnalyticalTable', () => {
124125
});
125126

126127
it('row count modes', () => {
127-
cy.mount(
128-
<div style={{ height: '200px' }}>
129-
<AnalyticalTable data={data} columns={columns} visibleRowCountMode={AnalyticalTableVisibleRowCountMode.Auto} />
130-
</div>
128+
[AnalyticalTableVisibleRowCountMode.Auto, AnalyticalTableVisibleRowCountMode.AutoWithEmptyRows].forEach(
129+
(visibleRowCountMode) => {
130+
cy.mount(
131+
<div style={{ height: '200px' }}>
132+
<AnalyticalTable
133+
data={data}
134+
columns={columns}
135+
visibleRowCountMode={visibleRowCountMode}
136+
overscanCount={10}
137+
/>
138+
</div>
139+
);
140+
cy.findByRole('grid').should('have.attr', 'data-per-page', '3');
141+
cy.findByText('X').should('be.visible');
142+
cy.findByText('C').should('not.be.visible');
143+
cy.get('[data-empty-row]').should('not.be.visible').should('have.length', 1);
144+
}
131145
);
132-
cy.findByRole('grid').should('have.attr', 'data-per-page', '3');
133-
cy.findByText('X').should('be.visible');
134-
cy.findByText('C').should('not.be.visible');
135-
136-
cy.mount(
137-
<AnalyticalTable
138-
style={{ height: '200px' }}
139-
data={data}
140-
columns={columns}
141-
visibleRowCountMode={AnalyticalTableVisibleRowCountMode.Auto}
142-
/>
146+
[AnalyticalTableVisibleRowCountMode.Auto, AnalyticalTableVisibleRowCountMode.AutoWithEmptyRows].forEach(
147+
(visibleRowCountMode) => {
148+
cy.mount(
149+
<AnalyticalTable
150+
style={{ height: '4400px' }}
151+
data={generateMoreData(200)}
152+
columns={columns}
153+
visibleRowCountMode={visibleRowCountMode}
154+
/>
155+
);
156+
cy.findByRole('grid').should('have.attr', 'data-per-page', '99'); //rows(99*44) + header(44) = 4400
157+
cy.findByText('Name-98').should('be.visible');
158+
cy.findByText('Name-99').should('not.be.visible');
159+
cy.get('[data-empty-row]').should('not.exist');
160+
}
143161
);
144-
cy.findByRole('grid').should('have.attr', 'data-per-page', '3');
145-
cy.findByText('X').should('be.visible');
146-
cy.findByText('C').should('not.be.visible');
147-
148-
cy.wait(1000);
149162

150-
cy.mount(
151-
<AnalyticalTable
152-
style={{ height: '4400px' }}
153-
data={generateMoreData(200)}
154-
columns={columns}
155-
visibleRowCountMode={AnalyticalTableVisibleRowCountMode.Auto}
156-
/>
163+
[AnalyticalTableVisibleRowCountMode.Auto, AnalyticalTableVisibleRowCountMode.AutoWithEmptyRows].forEach(
164+
(visibleRowCountMode) => {
165+
cy.mount(
166+
<AnalyticalTable
167+
style={{ height: '4400px' }}
168+
data={data}
169+
columns={columns}
170+
visibleRowCountMode={visibleRowCountMode}
171+
/>
172+
);
173+
if (visibleRowCountMode === AnalyticalTableVisibleRowCountMode.Auto) {
174+
cy.get('[data-empty-row]').should('be.visible').should('have.length', 1);
175+
} else {
176+
cy.get('[data-empty-row]').should('be.visible').should('have.length', 95);
177+
}
178+
}
157179
);
158-
cy.findByRole('grid').should('have.attr', 'data-per-page', '99'); //rows(99*44) + header(44) = 4400
159-
cy.findByText('Name-98').should('be.visible');
160-
cy.findByText('Name-99').should('not.be.visible');
161180

162-
//test if visibleRows prop is ignored when row-count-mode is "Auto"
163-
cy.mount(
164-
<AnalyticalTable
165-
style={{ height: '200px' }}
166-
data={data}
167-
columns={columns}
168-
visibleRowCountMode={AnalyticalTableVisibleRowCountMode.Auto}
169-
visibleRows={1337}
170-
/>
181+
//test if visibleRows prop is ignored when row-count-mode is "Auto" or "AutoWithEmptyRows"
182+
[AnalyticalTableVisibleRowCountMode.Auto, AnalyticalTableVisibleRowCountMode.AutoWithEmptyRows].forEach(
183+
(visibleRowCountMode) => {
184+
cy.mount(
185+
<AnalyticalTable
186+
style={{ height: '200px' }}
187+
data={data}
188+
columns={columns}
189+
visibleRowCountMode={visibleRowCountMode}
190+
visibleRows={1337}
191+
/>
192+
);
193+
cy.findByRole('grid').should('have.attr', 'data-per-page', '3');
194+
cy.findByText('X').should('be.visible');
195+
cy.findByText('C').should('not.be.visible');
196+
}
171197
);
172-
cy.findByRole('grid').should('have.attr', 'data-per-page', '3');
173-
cy.findByText('X').should('be.visible');
174-
cy.findByText('C').should('not.be.visible');
175198

176199
//test default visibleRow count
177200
cy.mount(

packages/main/src/components/AnalyticalTable/AnalyticalTable.mdx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -358,11 +358,15 @@ const TableWithSubcomponents = (props) => {
358358
359359
</details>
360360
361-
## Adjust the number of visible rows to the container height
361+
## Adjust the number of rows to the container height
362362
363-
By adding the `visibleRowCountMode` prop and setting it to `AnalyticalTableVisibleRowCountMode.Auto` the table automatically fills the surrounding container with rows.
363+
By adding the `visibleRowCountMode` prop and setting it to `AnalyticalTableVisibleRowCountMode.Auto` the table automatically fills the surrounding container with rows and when setting it to `AnalyticalTableVisibleRowCountMode.AutoWithEmptyRows`, empty rows fill the container as well, if not enough visible rows are available.
364364
365-
<ControlsWithNote of={ComponentStories.DynamicRowCount} include={['containerHeight']} hideHTMLPropsNote />
365+
<ControlsWithNote
366+
of={ComponentStories.DynamicRowCount}
367+
include={['containerHeight', 'visibleRowCountMode']}
368+
hideHTMLPropsNote
369+
/>
366370
367371
<Canvas sourceState="none" of={ComponentStories.DynamicRowCount} />
368372
@@ -376,6 +380,7 @@ const TableComponent = (props) => {
376380
data={props.data}
377381
columns={props.columns}
378382
visibleRowCountMode={AnalyticalTableVisibleRowCountMode.Auto}
383+
// visibleRowCountMode={AnalyticalTableVisibleRowCountMode.AutoWithEmptyRows}
379384
header={`Current height: ${props.containerHeight}px - Change the height in the table above`}
380385
/>
381386
</div>

packages/main/src/components/AnalyticalTable/AnalyticalTable.stories.tsx

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -495,15 +495,31 @@ export const DynamicRowCount = {
495495
}
496496
},
497497
render: (args) => {
498+
const [data, setData] = useState(args.data);
499+
const handleClick = () => {
500+
setData((prev) => {
501+
if (prev.length > 4) {
502+
return args.data.slice(0, 4);
503+
} else {
504+
return args.data;
505+
}
506+
});
507+
};
498508
return (
499-
<div style={{ height: `${args.containerHeight}px` }}>
500-
<AnalyticalTable
501-
data={args.data}
502-
columns={args.columns}
503-
visibleRowCountMode={args.visibleRowCountMode}
504-
header={`Current height: ${args.containerHeight}px - Change the height in the table above`}
505-
/>
506-
</div>
509+
<>
510+
<Button onClick={handleClick}>Toggle Number of Rows</Button>
511+
<br />
512+
<Text>Number of visible rows: {args.data.length}</Text>
513+
<hr />
514+
<div style={{ height: `${args.containerHeight}px` }}>
515+
<AnalyticalTable
516+
data={data}
517+
columns={args.columns}
518+
visibleRowCountMode={args.visibleRowCountMode}
519+
header={`Current height: ${args.containerHeight}px - Change the height in the table above`}
520+
/>
521+
</div>
522+
</>
507523
);
508524
}
509525
};

packages/main/src/components/AnalyticalTable/TableBody/VirtualTableBody.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ interface VirtualTableBodyProps {
1414
classes: Record<string, string>;
1515
prepareRow: (row: unknown) => void;
1616
rows: Record<string, any>[];
17-
minRows: number;
17+
itemCount: number;
1818
scrollToRef: MutableRefObject<ScrollToRefType>;
1919
isTreeTable: boolean;
2020
internalRowHeight: number;
@@ -48,7 +48,7 @@ export const VirtualTableBody = (props: VirtualTableBodyProps) => {
4848
classes,
4949
prepareRow,
5050
rows,
51-
minRows,
51+
itemCount,
5252
scrollToRef,
5353
isTreeTable,
5454
internalRowHeight,
@@ -71,7 +71,6 @@ export const VirtualTableBody = (props: VirtualTableBodyProps) => {
7171
triggerScroll
7272
} = props;
7373

74-
const itemCount = Math.max(minRows, rows.length);
7574
const overscan = overscanCount ? overscanCount : Math.floor(visibleRows / 2);
7675
const rowHeight = popInRowHeight !== internalRowHeight ? popInRowHeight : internalRowHeight;
7776
const lastNonEmptyRow = useRef(null);

packages/main/src/components/AnalyticalTable/index.tsx

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,11 @@ const AnalyticalTable = forwardRef<AnalyticalTableDomRef, AnalyticalTablePropTyp
356356
}, [tableRef.current, scaleXFactor]);
357357

358358
const updateRowsCount = useCallback(() => {
359-
if (visibleRowCountMode === AnalyticalTableVisibleRowCountMode.Auto && analyticalTableRef.current?.parentElement) {
359+
if (
360+
(visibleRowCountMode === AnalyticalTableVisibleRowCountMode.Auto ||
361+
visibleRowCountMode === AnalyticalTableVisibleRowCountMode.AutoWithEmptyRows) &&
362+
analyticalTableRef.current?.parentElement
363+
) {
360364
const parentElement = analyticalTableRef.current?.parentElement;
361365
const tableYPosition =
362366
parentElement &&
@@ -468,10 +472,16 @@ const AnalyticalTable = forwardRef<AnalyticalTableDomRef, AnalyticalTablePropTyp
468472
if (typeof tableState.bodyHeight === 'number') {
469473
return tableState.bodyHeight;
470474
}
471-
const rowNum = rows.length < internalVisibleRowCount ? Math.max(rows.length, minRows) : internalVisibleRowCount;
475+
let rowNum;
476+
if (visibleRowCountMode === AnalyticalTableVisibleRowCountMode.AutoWithEmptyRows) {
477+
rowNum = internalVisibleRowCount;
478+
} else {
479+
rowNum = rows.length < internalVisibleRowCount ? Math.max(rows.length, minRows) : internalVisibleRowCount;
480+
}
472481

473482
const rowHeight =
474483
visibleRowCountMode === AnalyticalTableVisibleRowCountMode.Auto ||
484+
visibleRowCountMode === AnalyticalTableVisibleRowCountMode.AutoWithEmptyRows ||
475485
tableState.interactiveRowsHavePopIn ||
476486
adjustTableHeightOnPopIn
477487
? popInRowHeight
@@ -731,7 +741,13 @@ const AnalyticalTable = forwardRef<AnalyticalTableDomRef, AnalyticalTablePropTyp
731741
classes={classes}
732742
prepareRow={prepareRow}
733743
rows={rows}
734-
minRows={minRows}
744+
itemCount={Math.max(
745+
minRows,
746+
rows.length,
747+
visibleRowCountMode === AnalyticalTableVisibleRowCountMode.AutoWithEmptyRows
748+
? internalVisibleRowCount
749+
: 0
750+
)}
735751
scrollToRef={scrollToRef}
736752
isTreeTable={isTreeTable}
737753
internalRowHeight={internalRowHeight}

packages/main/src/components/AnalyticalTable/types/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -344,15 +344,16 @@ export interface AnalyticalTablePropTypes extends Omit<CommonProps, 'title'> {
344344
*/
345345
minRows?: number;
346346
/**
347-
* Defines how the table will render visible rows.
347+
* Defines how the table will render rows.
348348
*
349349
* - __"Fixed":__ The table always has as many rows as defined in the `visibleRows` prop.
350350
* - __"Auto":__ The number of visible rows displayed depends on the height of the surrounding container.
351+
* - __"AutoWithEmptyRows":__ The number of rows displayed depends on the height of the surrounding container, if not enough visible rows are available, empty rows are displayed.
351352
* - __"Interactive":__ Adds a resizer to the bottom of the table to dynamically add or remove visible rows. The initial number of rows is defined by the `visibleRows` prop.
352353
*
353354
* __Default:__ `"Fixed"`
354355
*
355-
* __Note:__ When `"Auto"` is enabled, we recommend to use a fixed height for the parent container.
356+
* __Note:__ When `"Auto"` or `"AutoWithEmptyRows"` is enabled, we recommend using a fixed height for the parent container.
356357
*/
357358
visibleRowCountMode?:
358359
| AnalyticalTableVisibleRowCountMode

packages/main/src/enums/AnalyticalTableVisibleRowCountMode.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@ export enum AnalyticalTableVisibleRowCountMode {
1616
* __Note:__ When this is active, `visibleRows` prop has no effect.
1717
*/
1818
Auto = 'Auto',
19+
/**
20+
* The number of rows displayed depends on the height of the surrounding container, if not enough visible rows are available, empty rows are displayed.
21+
*
22+
* __Note:__ It's recommended to use a fixed height for the outer container.
23+
*
24+
* __Note:__ When this is active, `visibleRows` prop has no effect.
25+
*
26+
* @since 1.24.0
27+
*/
28+
AutoWithEmptyRows = 'AutoWithEmptyRows',
1929
/**
2030
* Adds a resizer to the bottom of the table to dynamically add or remove visible rows.
2131
* The initial number of rows is defined by the `visibleRows` prop.

packages/main/src/enums/TableVisibleRowCountMode.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export enum TableVisibleRowCountMode {
1414
* __Note:__ When this is active, `visibleRows` prop has no effect.
1515
*/
1616
Auto = 'Auto',
17+
AutoWithEmptyRows = 'AutoWithEmptyRows',
1718
/**
1819
* Adds a resizer to the bottom of the table to dynamically add or remove visible rows.
1920
* The initial number of rows is defined by the `visibleRows` prop.

0 commit comments

Comments
 (0)