Skip to content

Commit 907481f

Browse files
author
Vivian Hu
committed
Fix(tree):allow NestedTreeControl to have null or undefined child
1 parent 12bf619 commit 907481f

File tree

5 files changed

+50
-7
lines changed

5 files changed

+50
-7
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export abstract class BaseTreeControl<T> implements TreeControl<T> {
3434
isExpandable: (dataNode: T) => boolean;
3535

3636
/** Gets a stream that emits whenever the given data node's children change. */
37-
getChildren: (dataNode: T) => (Observable<T[]> | T[]);
37+
getChildren: (dataNode: T) => (Observable<T[]> | T[] | undefined | null);
3838

3939
/** Toggles one single data node's expanded/collapsed state. */
4040
toggle(dataNode: T): void {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {BaseTreeControl} from './base-tree-control';
1313
export class NestedTreeControl<T> extends BaseTreeControl<T> {
1414

1515
/** Construct with nested tree function getChildren. */
16-
constructor(public getChildren: (dataNode: T) => (Observable<T[]> | T[])) {
16+
constructor(public getChildren: (dataNode: T) => (Observable<T[]> | T[] | undefined | null)) {
1717
super();
1818
}
1919

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,5 +60,5 @@ export interface TreeControl<T> {
6060
readonly isExpandable: (dataNode: T) => boolean;
6161

6262
/** Gets a stream that emits whenever the given data node's children change. */
63-
readonly getChildren: (dataNode: T) => Observable<T[]> | T[];
63+
readonly getChildren: (dataNode: T) => Observable<T[]> | T[] | undefined | null;
6464
}

src/lib/tree/tree.spec.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,26 @@ describe('MatTree', () => {
237237
});
238238
});
239239

240+
describe('nested tree with undefined or null children', () => {
241+
describe('should initialize', () => {
242+
let fixture: ComponentFixture<MatNestedTreeWithNullOrUndefinedChild >;
243+
244+
beforeEach(() => {
245+
configureMatTreeTestingModule([MatNestedTreeWithNullOrUndefinedChild]);
246+
fixture = TestBed.createComponent(MatNestedTreeWithNullOrUndefinedChild);
247+
treeElement = fixture.nativeElement.querySelector('mat-tree');
248+
249+
fixture.detectChanges();
250+
});
251+
252+
it('with rendered dataNodes', () => {
253+
const nodes = getNodes(treeElement);
254+
255+
expect(nodes).toBeDefined('Expect nodes to be defined');
256+
expect(nodes[0].classList).toContain('customNodeClass');
257+
});
258+
});
259+
});
240260
describe('nested tree', () => {
241261
describe('should initialize', () => {
242262
let fixture: ComponentFixture<NestedMatTreeApp>;
@@ -710,6 +730,29 @@ class MatTreeWithNullOrUndefinedChild {
710730
hasChild = (_: number, node: ExampleFlatNode) => node.expandable;
711731
}
712732

733+
@Component({
734+
template: `
735+
<mat-tree [dataSource]="dataSource" [treeControl]="treeControl">
736+
<mat-nested-tree-node *matTreeNodeDef="let node" class="customNodeClass">
737+
{{node.name}}
738+
<ng-template matTreeNodeOutlet></ng-template>
739+
</mat-nested-tree-node>
740+
</mat-tree>
741+
`
742+
})
743+
class MatNestedTreeWithNullOrUndefinedChild {
744+
treeControl: NestedTreeControl<FoodNode>;
745+
dataSource: MatTreeNestedDataSource<FoodNode>;
746+
747+
constructor() {
748+
this.treeControl = new NestedTreeControl<FoodNode>(this.getChildren);
749+
this.dataSource = new MatTreeNestedDataSource();
750+
this.dataSource.data = TREE_DATA;
751+
}
752+
753+
private getChildren = (node: FoodNode) => node.children;
754+
}
755+
713756
@Component({
714757
template: `
715758
<mat-tree [dataSource]="dataSource" [treeControl]="treeControl">

tools/public_api_guard/cdk/tree.d.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
export declare abstract class BaseTreeControl<T> implements TreeControl<T> {
22
dataNodes: T[];
33
expansionModel: SelectionModel<T>;
4-
getChildren: (dataNode: T) => (Observable<T[]> | T[]);
4+
getChildren: (dataNode: T) => (Observable<T[]> | T[] | undefined | null);
55
getLevel: (dataNode: T) => number;
66
isExpandable: (dataNode: T) => boolean;
77
collapse(dataNode: T): void;
@@ -127,8 +127,8 @@ export declare function getTreeMultipleDefaultNodeDefsError(): Error;
127127
export declare function getTreeNoValidDataSourceError(): Error;
128128

129129
export declare class NestedTreeControl<T> extends BaseTreeControl<T> {
130-
getChildren: (dataNode: T) => (Observable<T[]> | T[]);
131-
constructor(getChildren: (dataNode: T) => (Observable<T[]> | T[]));
130+
getChildren: (dataNode: T) => (Observable<T[]> | T[] | undefined | null);
131+
constructor(getChildren: (dataNode: T) => (Observable<T[]> | T[] | undefined | null));
132132
protected _getDescendants(descendants: T[], dataNode: T): void;
133133
expandAll(): void;
134134
getDescendants(dataNode: T): T[];
@@ -137,7 +137,7 @@ export declare class NestedTreeControl<T> extends BaseTreeControl<T> {
137137
export interface TreeControl<T> {
138138
dataNodes: T[];
139139
expansionModel: SelectionModel<T>;
140-
readonly getChildren: (dataNode: T) => Observable<T[]> | T[];
140+
readonly getChildren: (dataNode: T) => Observable<T[]> | T[] | undefined | null;
141141
readonly getLevel: (dataNode: T) => number;
142142
readonly isExpandable: (dataNode: T) => boolean;
143143
collapse(dataNode: T): void;

0 commit comments

Comments
 (0)