Skip to content

Commit ed48142

Browse files
authored
fix(AnalyticalTable): offer limited support for infiniteScroll combined with a grouped table (#6431)
Using `infiniteScroll` with a grouped table can result in an odd user experience. For example, when rows are lazy-loaded via scrolling, new rows might only be added to existing groups. This won't change the scroll container's height, potentially forcing the user to scroll down again to load more rows. Therefore (and as we don't have a concept for this behavior) __it's not recommended using a grouped table in combination with `infiniteScroll`__!
1 parent b2942f8 commit ed48142

File tree

3 files changed

+19
-5
lines changed

3 files changed

+19
-5
lines changed

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

+13-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { enrichEventWithDetails } from '@ui5/webcomponents-react-base';
22
import type { MutableRefObject } from 'react';
33
import { useCallback, useEffect, useRef, useState } from 'react';
4-
import type { AnalyticalTablePropTypes } from '../types/index.js';
4+
import type { AnalyticalTablePropTypes, TableInstance } from '../types/index.js';
55

66
interface VirtualTableBodyContainerProps {
77
tableBodyHeight: number;
@@ -12,13 +12,14 @@ interface VirtualTableBodyContainerProps {
1212
infiniteScroll?: AnalyticalTablePropTypes['infiniteScroll'];
1313
infiniteScrollThreshold?: AnalyticalTablePropTypes['infiniteScrollThreshold'];
1414
onLoadMore: AnalyticalTablePropTypes['onLoadMore'];
15-
rows: Record<string, any>[];
15+
rows: TableInstance['rows'];
1616
internalRowHeight: number;
1717
handleExternalScroll: AnalyticalTablePropTypes['onTableScroll'];
1818
visibleRows: number;
1919
popInRowHeight: number;
2020
rowCollapsedFlag?: boolean;
2121
dispatch: (e: { type: string; payload?: any }) => void;
22+
isGrouped: boolean;
2223
}
2324

2425
export const VirtualTableBodyContainer = (props: VirtualTableBodyContainerProps) => {
@@ -37,6 +38,7 @@ export const VirtualTableBodyContainer = (props: VirtualTableBodyContainerProps)
3738
visibleRows,
3839
popInRowHeight,
3940
rowCollapsedFlag,
41+
isGrouped,
4042
dispatch
4143
} = props;
4244
const [isMounted, setIsMounted] = useState(false);
@@ -75,13 +77,19 @@ export const VirtualTableBodyContainer = (props: VirtualTableBodyContainerProps)
7577
handleExternalScroll(enrichEventWithDetails(event, { rows, rowElements: event.target.children[0].children }));
7678
const scrollOffset = event.target.scrollTop;
7779
const isScrollingDown = lastScrollTop.current < scrollOffset;
78-
if (isScrollingDown && infiniteScroll) {
80+
const target = event.target;
81+
const scrolledToBottom = target.scrollHeight - target.scrollTop === target.clientHeight;
82+
// For a grouped table, it is possible that no new groups (rows) are added since new rows are added to existing groups.
83+
// Because of this, the table should trigger the `onLoadMore` event every time a user scrolls to the bottom.
84+
const applyGroupingLogic = scrolledToBottom && isGrouped;
85+
86+
if ((isScrollingDown || applyGroupingLogic) && infiniteScroll) {
7987
lastScrollTop.current = scrollOffset;
8088
const currentLastRow =
8189
Math.floor(scrollOffset / popInRowHeight) +
8290
(popInRowHeight === internalRowHeight ? visibleRows : Math.floor(tableBodyHeight / popInRowHeight));
83-
if (rows.length - currentLastRow < infiniteScrollThreshold) {
84-
if (!firedInfiniteLoadEvents.current.has(rows.length)) {
91+
if (rows.length - currentLastRow < infiniteScrollThreshold || applyGroupingLogic) {
92+
if (!firedInfiniteLoadEvents.current.has(rows.length) || applyGroupingLogic) {
8593
onLoadMore(event);
8694
}
8795
firedInfiniteLoadEvents.current.add(rows.length);

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

+2
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ const AnalyticalTable = forwardRef<AnalyticalTableDomRef, AnalyticalTablePropTyp
276276

277277
const tableState: AnalyticalTableState = tableInstanceRef.current.state;
278278
const { triggerScroll } = tableState;
279+
const isGrouped = !!tableState.groupBy.length;
279280

280281
const noDataTextI18n = i18nBundle.getText(LIST_NO_DATA);
281282
const noDataTextFiltered = i18nBundle.getText(NO_DATA_FILTERED);
@@ -800,6 +801,7 @@ const AnalyticalTable = forwardRef<AnalyticalTableDomRef, AnalyticalTablePropTyp
800801
rows={rows}
801802
handleExternalScroll={handleBodyScroll}
802803
visibleRows={internalVisibleRowCount}
804+
isGrouped={isGrouped}
803805
>
804806
<VirtualTableBody
805807
scrollContainerRef={scrollContainerRef}

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

+4
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,8 @@ export interface AnalyticalTablePropTypes extends Omit<CommonProps, 'title'> {
692692
* Defines whether columns are groupable.
693693
*
694694
* __Note:__ This prop has no effect when `isTreeTable` is true or `renderRowSubComponent` is set.
695+
*
696+
* __Note:__ It is not recommended to use grouping in combination with `infiniteScroll` as there is no concept for this configuration.
695697
*/
696698
groupable?: boolean;
697699
/**
@@ -746,6 +748,8 @@ export interface AnalyticalTablePropTypes extends Omit<CommonProps, 'title'> {
746748
columnOrder?: string[];
747749
/**
748750
* Defines whether infinite scroll is active.
751+
*
752+
* __Note:__ It is not recommended to use this prop in combination with a grouped table, as there is no concept for this configuration.
749753
*/
750754
infiniteScroll?: boolean;
751755
/**

0 commit comments

Comments
 (0)