Skip to content

Commit 6b5ee26

Browse files
aferdkarelhala
andauthored
RHCLOUD-41872 add expandAll prop to DV TreeTable (#491)
* add expandAll prop * lint fix * Update packages/module/src/DataViewTableTree/DataViewTableTree.tsx Co-authored-by: Karel Hala <ch4rlien@gmail.com> --------- Co-authored-by: Karel Hala <ch4rlien@gmail.com>
1 parent e5382ac commit 6b5ee26

File tree

6 files changed

+1020
-9
lines changed

6 files changed

+1020
-9
lines changed

package-lock.json

Lines changed: 8 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/module/patternfly-docs/content/extensions/data-view/examples/Table/DataViewTableTreeExample.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { DataViewTable, DataViewTh, DataViewTrTree } from '@patternfly/react-dat
44
import { useDataViewSelection } from '@patternfly/react-data-view/dist/dynamic/Hooks';
55
import { FolderIcon, FolderOpenIcon, LeafIcon } from '@patternfly/react-icons';
66

7+
78
interface Repository {
89
name: string;
910
branches: string | null;

packages/module/patternfly-docs/content/extensions/data-view/examples/Table/Table.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ To define rows and columns for your table, use these props:
3939

4040
It is also possible to disable row selection using the `isSelectDisabled` function, which can be passed to the wrapping `DataView` component through the `selection` prop.
4141

42+
If you want to have all expandable nodes open on initial load pass the `expandAll` prop to the DataViewTable component
43+
4244
### Table example
4345
```js file="./DataViewTableExample.tsx"
4446

packages/module/src/DataViewTableTree/DataViewTableTree.test.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,15 @@ describe('DataViewTableTree component', () => {
101101
expect(container).toMatchSnapshot();
102102
});
103103

104+
test('should render tree table with all expandable nodes expanded', () => {
105+
const { container } = render(
106+
<DataView selection={mockSelection}>
107+
<DataViewTable isTreeTable aria-label='Repositories table' ouiaId={ouiaId} columns={columns} expandAll rows={rows} leafIcon={<LeafIcon/>} expandedIcon={<FolderOpenIcon aria-hidden />} collapsedIcon={<FolderIcon aria-hidden />} />
108+
</DataView>
109+
);
110+
expect(container).toMatchSnapshot();
111+
});
112+
104113
test('should render tree table with a loading state', () => {
105114
const { container } = render(
106115
<DataView activeState="loading">

packages/module/src/DataViewTableTree/DataViewTableTree.tsx

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { FC, useState, useMemo, ReactNode } from 'react';
1+
import { FC, useState, useMemo, useEffect, ReactNode } from 'react';
22
import {
33
Table,
44
TableProps,
@@ -67,6 +67,8 @@ export interface DataViewTableTreeProps extends Omit<TableProps, 'onSelect' | 'r
6767
expandedIcon?: React.ReactNode;
6868
/** Optional icon for the collapsed parent rows */
6969
collapsedIcon?: React.ReactNode;
70+
/** Expand all expandable nodes on initial load */
71+
expandAll?: boolean;
7072
/** Custom OUIA ID */
7173
ouiaId?: string;
7274
}
@@ -79,6 +81,7 @@ export const DataViewTableTree: FC<DataViewTableTreeProps> = ({
7981
leafIcon = null,
8082
expandedIcon = null,
8183
collapsedIcon = null,
84+
expandAll = false,
8285
ouiaId = 'DataViewTableTree',
8386
...props
8487
}: DataViewTableTreeProps) => {
@@ -87,6 +90,37 @@ export const DataViewTableTree: FC<DataViewTableTreeProps> = ({
8790
const [ expandedNodeIds, setExpandedNodeIds ] = useState<string[]>([]);
8891
const [ expandedDetailsNodeNames, setExpandedDetailsNodeIds ] = useState<string[]>([]);
8992

93+
// Helper function to collect all node IDs that have children (are expandable)
94+
const getExpandableNodeIds = (nodes: DataViewTrTree[]): string[] => {
95+
const expandableIds: string[] = [];
96+
97+
const traverse = (nodeList: DataViewTrTree[]) => {
98+
nodeList.forEach(node => {
99+
if (node.children && node.children.length > 0) {
100+
expandableIds.push(node.id);
101+
traverse(node.children);
102+
}
103+
});
104+
};
105+
106+
traverse(nodes);
107+
return expandableIds;
108+
};
109+
110+
// Effect to handle expandAll behavior
111+
// Memoize the expandable IDs to avoid recalculating when rows object reference changes but structure is the same
112+
const expandableIds = useMemo(() => getExpandableNodeIds(rows), [ rows ]);
113+
114+
// Effect to handle expandAll behavior - only runs when IDs actually change
115+
useEffect(() => {
116+
if (expandAll) {
117+
setExpandedNodeIds(expandableIds);
118+
} else {
119+
setExpandedNodeIds([]);
120+
}
121+
// eslint-disable-next-line react-hooks/exhaustive-deps
122+
}, [ expandAll, expandableIds.join(',') ]);
123+
90124
const activeHeadState = useMemo(() => activeState ? headStates?.[activeState] : undefined, [ activeState, headStates ]);
91125
const activeBodyState = useMemo(() => activeState ? bodyStates?.[activeState] : undefined, [ activeState, bodyStates ]);
92126

0 commit comments

Comments
 (0)