Skip to content

Commit 364376e

Browse files
crisbetojelbourn
authored andcommitted
fix(tree): handle null children in nested tree (#14547)
Gracefully handles nodes whose children are set to null. This seems to be something that we used to handle until a regression from #10886. Fixes #14545.
1 parent 8a3d21a commit 364376e

File tree

2 files changed

+20
-5
lines changed

2 files changed

+20
-5
lines changed

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

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import {fakeAsync, flush} from '@angular/core/testing';
12
import {of as observableOf} from 'rxjs';
23
import {NestedTreeControl} from './nested-tree-control';
34

@@ -92,6 +93,20 @@ describe('CdkNestedTreeControl', () => {
9293
.toBe(totalNumber, `Expect ${totalNumber} expanded nodes`);
9394
});
9495

96+
// Note that this needs to be `fakeAsync` in order to
97+
// catch the error inside an observable correctly.
98+
it('should handle null children', fakeAsync(() => {
99+
const nodes = generateData(3, 2);
100+
101+
nodes[1].children = null!;
102+
treeControl.dataNodes = nodes;
103+
104+
expect(() => {
105+
treeControl.expandAll();
106+
flush();
107+
}).not.toThrow();
108+
}));
109+
95110
describe('with children array', () => {
96111
let getStaticChildren = (node: TestData) => node.children;
97112

@@ -201,12 +216,12 @@ export class TestData {
201216

202217
function generateData(dataLength: number, childLength: number, grandChildLength: number = 0)
203218
: TestData[] {
204-
let data = <any>[];
219+
let data: TestData[] = [];
205220
let nextIndex = 0;
206221
for (let i = 0; i < dataLength; i++) {
207-
let children = <any>[];
222+
let children: TestData[] = [];
208223
for (let j = 0; j < childLength; j++) {
209-
let grandChildren = <any>[];
224+
let grandChildren: TestData[] = [];
210225
for (let k = 0; k < grandChildLength; k++) {
211226
grandChildren.push(new TestData(`a_${nextIndex}`, `b_${nextIndex}`, `c_${nextIndex++}`, 3));
212227
}

src/cdk/tree/control/nested-tree-control.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88
import {Observable} from 'rxjs';
9-
import {take} from 'rxjs/operators';
9+
import {take, filter} from 'rxjs/operators';
1010
import {BaseTreeControl} from './base-tree-control';
1111

1212
/** Nested tree control. Able to expand/collapse a subtree recursively for NestedNode type. */
@@ -46,7 +46,7 @@ export class NestedTreeControl<T> extends BaseTreeControl<T> {
4646
if (Array.isArray(childrenNodes)) {
4747
childrenNodes.forEach((child: T) => this._getDescendants(descendants, child));
4848
} else if (childrenNodes instanceof Observable) {
49-
childrenNodes.pipe(take(1)).subscribe(children => {
49+
childrenNodes.pipe(take(1), filter(Boolean)).subscribe(children => {
5050
children.forEach((child: T) => this._getDescendants(descendants, child));
5151
});
5252
}

0 commit comments

Comments
 (0)