mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
Fix(tree):allow NestedTreeControl to have null or undefined child (#14601)
This commit is contained in:
@@ -34,7 +34,7 @@ export abstract class BaseTreeControl<T> implements TreeControl<T> {
|
||||
isExpandable: (dataNode: T) => boolean;
|
||||
|
||||
/** Gets a stream that emits whenever the given data node's children change. */
|
||||
getChildren: (dataNode: T) => (Observable<T[]> | T[]);
|
||||
getChildren: (dataNode: T) => (Observable<T[]> | T[] | undefined | null);
|
||||
|
||||
/** Toggles one single data node's expanded/collapsed state. */
|
||||
toggle(dataNode: T): void {
|
||||
|
||||
@@ -13,7 +13,7 @@ import {BaseTreeControl} from './base-tree-control';
|
||||
export class NestedTreeControl<T> extends BaseTreeControl<T> {
|
||||
|
||||
/** Construct with nested tree function getChildren. */
|
||||
constructor(public getChildren: (dataNode: T) => (Observable<T[]> | T[])) {
|
||||
constructor(public getChildren: (dataNode: T) => (Observable<T[]> | T[] | undefined | null)) {
|
||||
super();
|
||||
}
|
||||
|
||||
|
||||
@@ -60,5 +60,5 @@ export interface TreeControl<T> {
|
||||
readonly isExpandable: (dataNode: T) => boolean;
|
||||
|
||||
/** Gets a stream that emits whenever the given data node's children change. */
|
||||
readonly getChildren: (dataNode: T) => Observable<T[]> | T[];
|
||||
readonly getChildren: (dataNode: T) => Observable<T[]> | T[] | undefined | null;
|
||||
}
|
||||
|
||||
@@ -237,6 +237,26 @@ describe('MatTree', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('nested tree with undefined or null children', () => {
|
||||
describe('should initialize', () => {
|
||||
let fixture: ComponentFixture<MatNestedTreeWithNullOrUndefinedChild >;
|
||||
|
||||
beforeEach(() => {
|
||||
configureMatTreeTestingModule([MatNestedTreeWithNullOrUndefinedChild]);
|
||||
fixture = TestBed.createComponent(MatNestedTreeWithNullOrUndefinedChild);
|
||||
treeElement = fixture.nativeElement.querySelector('mat-tree');
|
||||
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('with rendered dataNodes', () => {
|
||||
const nodes = getNodes(treeElement);
|
||||
|
||||
expect(nodes).toBeDefined('Expect nodes to be defined');
|
||||
expect(nodes[0].classList).toContain('customNodeClass');
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('nested tree', () => {
|
||||
describe('should initialize', () => {
|
||||
let fixture: ComponentFixture<NestedMatTreeApp>;
|
||||
@@ -710,6 +730,29 @@ class MatTreeWithNullOrUndefinedChild {
|
||||
hasChild = (_: number, node: ExampleFlatNode) => node.expandable;
|
||||
}
|
||||
|
||||
@Component({
|
||||
template: `
|
||||
<mat-tree [dataSource]="dataSource" [treeControl]="treeControl">
|
||||
<mat-nested-tree-node *matTreeNodeDef="let node" class="customNodeClass">
|
||||
{{node.name}}
|
||||
<ng-template matTreeNodeOutlet></ng-template>
|
||||
</mat-nested-tree-node>
|
||||
</mat-tree>
|
||||
`
|
||||
})
|
||||
class MatNestedTreeWithNullOrUndefinedChild {
|
||||
treeControl: NestedTreeControl<FoodNode>;
|
||||
dataSource: MatTreeNestedDataSource<FoodNode>;
|
||||
|
||||
constructor() {
|
||||
this.treeControl = new NestedTreeControl<FoodNode>(this.getChildren);
|
||||
this.dataSource = new MatTreeNestedDataSource();
|
||||
this.dataSource.data = TREE_DATA;
|
||||
}
|
||||
|
||||
private getChildren = (node: FoodNode) => node.children;
|
||||
}
|
||||
|
||||
@Component({
|
||||
template: `
|
||||
<mat-tree [dataSource]="dataSource" [treeControl]="treeControl">
|
||||
|
||||
Vendored
+4
-4
@@ -1,7 +1,7 @@
|
||||
export declare abstract class BaseTreeControl<T> implements TreeControl<T> {
|
||||
dataNodes: T[];
|
||||
expansionModel: SelectionModel<T>;
|
||||
getChildren: (dataNode: T) => (Observable<T[]> | T[]);
|
||||
getChildren: (dataNode: T) => (Observable<T[]> | T[] | undefined | null);
|
||||
getLevel: (dataNode: T) => number;
|
||||
isExpandable: (dataNode: T) => boolean;
|
||||
collapse(dataNode: T): void;
|
||||
@@ -127,8 +127,8 @@ export declare function getTreeMultipleDefaultNodeDefsError(): Error;
|
||||
export declare function getTreeNoValidDataSourceError(): Error;
|
||||
|
||||
export declare class NestedTreeControl<T> extends BaseTreeControl<T> {
|
||||
getChildren: (dataNode: T) => (Observable<T[]> | T[]);
|
||||
constructor(getChildren: (dataNode: T) => (Observable<T[]> | T[]));
|
||||
getChildren: (dataNode: T) => (Observable<T[]> | T[] | undefined | null);
|
||||
constructor(getChildren: (dataNode: T) => (Observable<T[]> | T[] | undefined | null));
|
||||
protected _getDescendants(descendants: T[], dataNode: T): void;
|
||||
expandAll(): void;
|
||||
getDescendants(dataNode: T): T[];
|
||||
@@ -137,7 +137,7 @@ export declare class NestedTreeControl<T> extends BaseTreeControl<T> {
|
||||
export interface TreeControl<T> {
|
||||
dataNodes: T[];
|
||||
expansionModel: SelectionModel<T>;
|
||||
readonly getChildren: (dataNode: T) => Observable<T[]> | T[];
|
||||
readonly getChildren: (dataNode: T) => Observable<T[]> | T[] | undefined | null;
|
||||
readonly getLevel: (dataNode: T) => number;
|
||||
readonly isExpandable: (dataNode: T) => boolean;
|
||||
collapse(dataNode: T): void;
|
||||
|
||||
Reference in New Issue
Block a user