Skip to content

Commit b76fc5b

Browse files
committed
fix(cdk/tree): cdk tree with levelAccessor should only render expended nodes instead of all nodes
1 parent 8cf7615 commit b76fc5b

File tree

6 files changed

+98
-21
lines changed

6 files changed

+98
-21
lines changed

src/cdk/tree/tree-with-tree-control.spec.ts

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,12 @@ describe('CdkTree with TreeControl', () => {
133133
dataSource.addChild(data[0], true);
134134
fixture.detectChanges();
135135

136-
const ariaLevels = getNodes(treeElement).map(n => n.getAttribute('aria-level'));
136+
let ariaLevels = getNodes(treeElement).map(n => n.getAttribute('aria-level'));
137+
expect(ariaLevels).toEqual(['2', '2', '2']);
138+
139+
component.treeControl.expandAll();
140+
fixture.detectChanges();
141+
ariaLevels = getNodes(treeElement).map(n => n.getAttribute('aria-level'));
137142
expect(ariaLevels).toEqual(['2', '3', '2', '2']);
138143
});
139144

@@ -143,7 +148,7 @@ describe('CdkTree with TreeControl', () => {
143148
dataSource.addChild(data[2]);
144149
fixture.detectChanges();
145150
let ariaExpandedStates = getNodes(treeElement).map(n => n.getAttribute('aria-expanded'));
146-
expect(ariaExpandedStates).toEqual([null, null, 'false', null]);
151+
expect(ariaExpandedStates).toEqual([null, null, 'false']);
147152

148153
component.treeControl.expandAll();
149154
fixture.detectChanges();
@@ -387,6 +392,17 @@ describe('CdkTree with TreeControl', () => {
387392
treeElement = fixture.nativeElement.querySelector('cdk-tree');
388393
data = dataSource.data;
389394
expect(data.length).toBe(4);
395+
expectFlatTreeToMatch(
396+
treeElement,
397+
28,
398+
'px',
399+
[`[topping_1] - [cheese_1] + [base_1]`],
400+
[`[topping_2] - [cheese_2] + [base_2]`],
401+
[`[topping_3] - [cheese_3] + [base_3]`],
402+
);
403+
component.treeControl.expandAll();
404+
fixture.detectChanges();
405+
treeElement = fixture.nativeElement.querySelector('cdk-tree');
390406
expectFlatTreeToMatch(
391407
treeElement,
392408
28,
@@ -434,6 +450,18 @@ describe('CdkTree with TreeControl', () => {
434450
treeElement = fixture.nativeElement.querySelector('cdk-tree');
435451
data = dataSource.data;
436452
expect(data.length).toBe(4);
453+
expectFlatTreeToMatch(
454+
treeElement,
455+
28,
456+
'px',
457+
[`[topping_1] - [cheese_1] + [base_1]`],
458+
[`[topping_2] - [cheese_2] + [base_2]`],
459+
[`[topping_3] - [cheese_3] + [base_3]`],
460+
);
461+
462+
(getNodes(treeElement)[1] as HTMLElement).click();
463+
fixture.detectChanges();
464+
treeElement = fixture.nativeElement.querySelector('cdk-tree');
437465
expectFlatTreeToMatch(
438466
treeElement,
439467
28,
@@ -481,6 +509,18 @@ describe('CdkTree with TreeControl', () => {
481509
treeElement = fixture.nativeElement.querySelector('cdk-tree');
482510
data = dataSource.data;
483511
expect(data.length).toBe(4);
512+
expectFlatTreeToMatch(
513+
treeElement,
514+
28,
515+
'px',
516+
[`[topping_1] - [cheese_1] + [base_1]`],
517+
[`[topping_2] - [cheese_2] + [base_2]`],
518+
[`[topping_3] - [cheese_3] + [base_3]`],
519+
);
520+
521+
(getNodes(treeElement)[1] as HTMLElement).click();
522+
fixture.detectChanges();
523+
treeElement = fixture.nativeElement.querySelector('cdk-tree');
484524
expectFlatTreeToMatch(
485525
treeElement,
486526
28,

src/cdk/tree/tree.spec.ts

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,12 @@ describe('CdkTree', () => {
139139
dataSource.addChild(data[0], true);
140140
fixture.detectChanges();
141141

142-
const ariaLevels = getNodes(treeElement).map(n => n.getAttribute('aria-level'));
142+
let ariaLevels = getNodes(treeElement).map(n => n.getAttribute('aria-level'));
143+
expect(ariaLevels).toEqual(['2', '2', '2']);
144+
145+
tree.expandAll();
146+
fixture.detectChanges();
147+
ariaLevels = getNodes(treeElement).map(n => n.getAttribute('aria-level'));
143148
expect(ariaLevels).toEqual(['2', '3', '2', '2']);
144149
});
145150

@@ -149,7 +154,7 @@ describe('CdkTree', () => {
149154
dataSource.addChild(data[2]);
150155
fixture.detectChanges();
151156
let ariaExpandedStates = getNodes(treeElement).map(n => n.getAttribute('aria-expanded'));
152-
expect(ariaExpandedStates).toEqual([null, null, 'false', null]);
157+
expect(ariaExpandedStates).toEqual([null, null, 'false']);
153158

154159
component.tree.expandAll();
155160
fixture.detectChanges();
@@ -334,7 +339,7 @@ describe('CdkTree', () => {
334339

335340
expect(getNodes(treeElement).map(x => x.getAttribute('tabindex')))
336341
.withContext(`Expecting parent node to be focused since it was collapsed.`)
337-
.toEqual(['0', '-1']);
342+
.toEqual(['0']);
338343
});
339344

340345
it('should expand/collapse the node recursively', () => {
@@ -439,6 +444,18 @@ describe('CdkTree', () => {
439444
treeElement = fixture.nativeElement.querySelector('cdk-tree');
440445
data = dataSource.data;
441446
expect(data.length).toBe(4);
447+
expectFlatTreeToMatch(
448+
treeElement,
449+
28,
450+
'px',
451+
[`[topping_1] - [cheese_1] + [base_1]`],
452+
[`[topping_2] - [cheese_2] + [base_2]`],
453+
[`[topping_3] - [cheese_3] + [base_3]`],
454+
);
455+
456+
tree.expandAll();
457+
fixture.detectChanges();
458+
treeElement = fixture.nativeElement.querySelector('cdk-tree');
442459
expectFlatTreeToMatch(
443460
treeElement,
444461
28,
@@ -485,6 +502,18 @@ describe('CdkTree', () => {
485502
treeElement = fixture.nativeElement.querySelector('cdk-tree');
486503
data = dataSource.data;
487504
expect(data.length).toBe(4);
505+
expectFlatTreeToMatch(
506+
treeElement,
507+
28,
508+
'px',
509+
[`[topping_1] - [cheese_1] + [base_1]`],
510+
[`[topping_2] - [cheese_2] + [base_2]`],
511+
[`[topping_3] - [cheese_3] + [base_3]`],
512+
);
513+
514+
tree.expandAll();
515+
fixture.detectChanges();
516+
treeElement = fixture.nativeElement.querySelector('cdk-tree');
488517
expectFlatTreeToMatch(
489518
treeElement,
490519
28,
@@ -532,6 +561,18 @@ describe('CdkTree', () => {
532561
treeElement = fixture.nativeElement.querySelector('cdk-tree');
533562
data = dataSource.data;
534563
expect(data.length).toBe(4);
564+
expectFlatTreeToMatch(
565+
treeElement,
566+
28,
567+
'px',
568+
[`[topping_1] - [cheese_1] + [base_1]`],
569+
[`[topping_2] - [cheese_2] + [base_2]`],
570+
[`[topping_3] - [cheese_3] + [base_3]`],
571+
);
572+
573+
tree.expandAll();
574+
fixture.detectChanges();
575+
treeElement = fixture.nativeElement.querySelector('cdk-tree');
535576
expectFlatTreeToMatch(
536577
treeElement,
537578
28,

src/cdk/tree/tree.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,6 +1049,12 @@ export class CdkTree<T, K = T>
10491049
);
10501050
}
10511051

1052+
private _shouldFlattenNodeRender(node: T): boolean {
1053+
const key = this._getExpansionKey(node);
1054+
const parent = this._parents.get(key);
1055+
return !parent || (this.isExpanded(parent) && this._shouldFlattenNodeRender(parent));
1056+
}
1057+
10521058
/**
10531059
* Converts children for certain tree configurations.
10541060
*
@@ -1095,10 +1101,12 @@ export class CdkTree<T, K = T>
10951101
// with the TreeControl, and so no conversions are necessary. Otherwise,
10961102
// we've already confirmed that the data model matches up with the
10971103
// desired node type here.
1098-
return observableOf({renderNodes: nodes, flattenedNodes: nodes}).pipe(
1099-
tap(({flattenedNodes}) => {
1100-
this._calculateParents(flattenedNodes);
1101-
}),
1104+
return observableOf(nodes).pipe(
1105+
tap(nodes => this._calculateParents(nodes)),
1106+
map(nodes => ({
1107+
renderNodes: nodes.filter(node => this._shouldFlattenNodeRender(node)),
1108+
flattenedNodes: nodes,
1109+
})),
11021110
);
11031111
} else {
11041112
// clear previously generated data so we don't keep end up retaining data overtime causing

src/components-examples/cdk/tree/cdk-tree-flat-children-accessor/cdk-tree-flat-children-accessor-example.html

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
<cdk-tree #tree [dataSource]="dataSource" [childrenAccessor]="childrenAccessor">
22
<!-- This is the tree node template for leaf nodes -->
33
<cdk-tree-node *cdkTreeNodeDef="let node" cdkTreeNodePadding
4-
[style.display]="shouldRender(node) ? 'flex' : 'none'"
5-
[isDisabled]="!shouldRender(node)"
64
class="example-tree-node">
75
<!-- use a disabled button to provide padding for tree leaf -->
86
<button matIconButton disabled></button>
@@ -12,8 +10,6 @@
1210
<cdk-tree-node *cdkTreeNodeDef="let node; when: hasChild" cdkTreeNodePadding
1311
cdkTreeNodeToggle
1412
[cdkTreeNodeTypeaheadLabel]="node.name"
15-
[style.display]="shouldRender(node) ? 'flex' : 'none'"
16-
[isDisabled]="!shouldRender(node)"
1713
[isExpandable]="true"
1814
class="example-tree-node">
1915
<button matIconButton cdkTreeNodeToggle [attr.aria-label]="'Toggle ' + node.name">

src/components-examples/cdk/tree/cdk-tree-flat-level-accessor/cdk-tree-flat-level-accessor-example.html

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
<cdk-tree #tree [dataSource]="dataSource" [levelAccessor]="levelAccessor">
22
<!-- This is the tree node template for leaf nodes -->
33
<cdk-tree-node *cdkTreeNodeDef="let node" cdkTreeNodePadding
4-
[style.display]="shouldRender(node) ? 'flex' : 'none'"
5-
[isDisabled]="!shouldRender(node)"
64
class="example-tree-node">
75
<!-- use a disabled button to provide padding for tree leaf -->
86
<button matIconButton disabled></button>
@@ -12,8 +10,6 @@
1210
<cdk-tree-node *cdkTreeNodeDef="let node; when: hasChild" cdkTreeNodePadding
1311
cdkTreeNodeToggle
1412
[cdkTreeNodeTypeaheadLabel]="node.name"
15-
[style.display]="shouldRender(node) ? 'flex' : 'none'"
16-
[isDisabled]="!shouldRender(node)"
1713
[isExpandable]="node.expandable"
1814
class="example-tree-node">
1915
<button matIconButton cdkTreeNodeToggle

src/components-examples/cdk/tree/cdk-tree-flat/cdk-tree-flat-example.html

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
<cdk-tree [dataSource]="dataSource" [treeControl]="treeControl">
22
<!-- This is the tree node template for leaf nodes -->
33
<cdk-tree-node *cdkTreeNodeDef="let node" cdkTreeNodePadding
4-
[style.display]="shouldRender(node) ? 'flex' : 'none'"
5-
[isDisabled]="!shouldRender(node)"
64
class="example-tree-node">
75
<!-- use a disabled button to provide padding for tree leaf -->
86
<button matIconButton disabled></button>
@@ -11,8 +9,6 @@
119
<!-- This is the tree node template for expandable nodes -->
1210
<cdk-tree-node *cdkTreeNodeDef="let node; when: hasChild" cdkTreeNodePadding
1311
cdkTreeNodeToggle [cdkTreeNodeTypeaheadLabel]="node.name"
14-
[style.display]="shouldRender(node) ? 'flex' : 'none'"
15-
[isDisabled]="!shouldRender(node)"
1612
(expandedChange)="node.isExpanded = $event"
1713
class="example-tree-node">
1814
<button matIconButton cdkTreeNodeToggle

0 commit comments

Comments
 (0)