fix(tree): fix type error in tree (#10095)

This commit is contained in:
tinayuangao
2018-02-22 11:01:51 -08:00
committed by Joey Perrott
parent 19463bb6c9
commit 6d94aec797
6 changed files with 86 additions and 13 deletions
+4
View File
@@ -17,6 +17,7 @@ import {takeUntil} from 'rxjs/operators/takeUntil';
import {CdkTree, CdkTreeNode} from './tree';
import {CdkTreeNodeOutlet} from './outlet';
import {getTreeControlFunctionsMissingError} from './tree-errors';
/**
* Nested node is a child of `<cdk-tree>`. It works with nested tree.
@@ -62,6 +63,9 @@ export class CdkNestedTreeNode<T> extends CdkTreeNode<T> implements AfterContent
}
ngAfterContentInit() {
if (!this._tree.treeControl.getChildren) {
throw getTreeControlFunctionsMissingError();
}
this._tree.treeControl.getChildren(this.data).pipe(takeUntil(this._destroyed))
.subscribe(result => {
if (result && result.length) {
+67
View File
@@ -14,11 +14,13 @@ import {Observable} from 'rxjs/Observable';
import {combineLatest} from 'rxjs/observable/combineLatest';
import {map} from 'rxjs/operators/map';
import {BaseTreeControl} from './control/base-tree-control';
import {TreeControl} from './control/tree-control';
import {FlatTreeControl} from './control/flat-tree-control';
import {NestedTreeControl} from './control/nested-tree-control';
import {CdkTreeModule} from './index';
import {CdkTree} from './tree';
import {getTreeControlFunctionsMissingError} from './tree-errors';
describe('CdkTree', () => {
@@ -587,6 +589,18 @@ describe('CdkTree', () => {
[`[topping_3] - [cheese_3] + [base_3]`]);
});
});
it('should throw an error when missing function in nested tree', () => {
configureCdkTreeTestingModule([NestedCdkErrorTreeApp]);
expect(() => TestBed.createComponent(NestedCdkErrorTreeApp).detectChanges())
.toThrowError(getTreeControlFunctionsMissingError().message);
});
it('should throw an error when missing function in flat tree', () => {
configureCdkTreeTestingModule([FlatCdkErrorTreeApp]);
expect(() => TestBed.createComponent(FlatCdkErrorTreeApp).detectChanges())
.toThrowError(getTreeControlFunctionsMissingError().message);
});
});
});
@@ -994,3 +1008,56 @@ class ObservableDataSourceNestedCdkTreeApp {
@ViewChild(CdkTree) tree: CdkTree<TestData>;
}
@Component({
template: `
<cdk-tree [dataSource]="dataSource" [treeControl]="treeControl">
<cdk-nested-tree-node *cdkTreeNodeDef="let node" class="customNodeClass">
{{node.pizzaTopping}} - {{node.pizzaCheese}} + {{node.pizzaBase}}
<ng-template cdkTreeNodeOutlet></ng-template>
</cdk-nested-tree-node>
</cdk-tree>
`
})
class NestedCdkErrorTreeApp {
getLevel = (node: TestData) => node.level;
isExpandable = (node: TestData) => node.children.length > 0;
treeControl: TreeControl<TestData> = new FlatTreeControl(this.getLevel, this.isExpandable);
dataSource: FakeDataSource | null = new FakeDataSource(this.treeControl);
@ViewChild(CdkTree) tree: CdkTree<TestData>;
}
class FakeTreeControl extends BaseTreeControl<TestData> {
getDescendants(_: TestData): TestData[] {
return this.dataNodes;
}
expandAll(): void {
// No op
}
}
@Component({
template: `
<cdk-tree [dataSource]="dataSource" [treeControl]="treeControl">
<cdk-tree-node *cdkTreeNodeDef="let node" class="customNodeClass">
{{node.pizzaTopping}} - {{node.pizzaCheese}} + {{node.pizzaBase}}
<ng-template cdkTreeNodeOutlet></ng-template>
</cdk-tree-node>
</cdk-tree>
`
})
class FlatCdkErrorTreeApp {
getLevel = (node: TestData) => node.level;
isExpandable = (node: TestData) => node.children.length > 0;
treeControl: TreeControl<TestData> = new FakeTreeControl();
dataSource: FakeDataSource | null = new FakeDataSource(this.treeControl);
@ViewChild(CdkTree) tree: CdkTree<TestData>;
}
+5 -5
View File
@@ -60,7 +60,7 @@ export class CdkTreeNode<T> implements FocusableOption, OnDestroy {
* The most recently created `CdkTreeNode`. We save it in static variable so we can retrieve it
* in `CdkTree` and set the data to it.
*/
static mostRecentTreeNode: CdkTreeNode<any> | null = null;
static mostRecentTreeNode: CdkTreeNode<{}> | null = null;
/** Subject that emits when the component has been destroyed. */
protected _destroyed = new Subject<void>();
@@ -89,7 +89,7 @@ export class CdkTreeNode<T> implements FocusableOption, OnDestroy {
constructor(protected _elementRef: ElementRef,
protected _tree: CdkTree<T>) {
CdkTreeNode.mostRecentTreeNode = this;
CdkTreeNode.mostRecentTreeNode = this as CdkTreeNode<T>;
}
ngOnDestroy() {
@@ -140,7 +140,7 @@ export class CdkTree<T> implements CollectionViewer, OnInit, OnDestroy {
private _onDestroy = new Subject<void>();
/** Latest data provided by the data source through the connect interface. */
private _data: Array<T> = new Array<T>();
private _data = new Array<T>();
/** Differ used to find the changes in the data provided by the data source. */
private _dataDiffer: IterableDiffer<T>;
@@ -304,7 +304,7 @@ export class CdkTree<T> implements CollectionViewer, OnInit, OnDestroy {
* definition.
*/
_getNodeDef(data: T, i: number): CdkTreeNodeDef<T> {
if (this._nodeDefs.length == 1) { return this._nodeDefs.first; }
if (this._nodeDefs.length === 1) { return this._nodeDefs.first; }
const nodeDef =
this._nodeDefs.find(def => def.when && def.when(i, data)) || this._defaultNodeDef;
@@ -321,7 +321,7 @@ export class CdkTree<T> implements CollectionViewer, OnInit, OnDestroy {
const node = this._getNodeDef(nodeData, index);
// Node context that will be provided to created embedded view
const context: CdkTreeNodeOutletContext<T> = new CdkTreeNodeOutletContext<T>(nodeData);
const context = new CdkTreeNodeOutletContext<T>(nodeData);
// Use default tree nodeOutlet, or nested node's nodeOutlet
const container = viewContainer ? viewContainer : this._nodeOutlet.viewContainer;
@@ -11,6 +11,7 @@ import {SelectionModel} from '@angular/cdk/collections';
import {FlatTreeControl} from '@angular/cdk/tree';
import {MatTreeFlattener, MatTreeFlatDataSource} from '@angular/material/tree';
import {of as ofObservable} from 'rxjs/observable/of';
import {Observable} from 'rxjs/Observable';
import {TodoItemNode, TodoItemFlatNode, ChecklistDatabase} from './checklist-database';
/**
@@ -61,7 +62,9 @@ export class ChecklistTreeDemo {
isExpandable = (node: TodoItemFlatNode) => { return node.expandable; };
getChildren = (node: TodoItemNode) => { return ofObservable(node.children); };
getChildren = (node: TodoItemNode): Observable<TodoItemNode[]> => {
return ofObservable(node.children);
}
hasChild = (_: number, _nodeData: TodoItemFlatNode) => { return _nodeData.expandable; };
@@ -9,6 +9,7 @@ import {Injectable} from '@angular/core';
import {FlatTreeControl} from '@angular/cdk/tree';
import {CollectionViewer, SelectionChange} from '@angular/cdk/collections';
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
import {Observable} from 'rxjs/Observable';
import {merge} from 'rxjs/observable/merge';
import {map} from 'rxjs/operators/map';
@@ -67,12 +68,9 @@ export class DynamicDataSource {
constructor(private treeControl: FlatTreeControl<DynamicFlatNode>,
private database: DynamicDatabase) {}
connect(collectionViewer: CollectionViewer) {
const changes = [
collectionViewer.viewChange,
this.treeControl.expansionModel.onChange!,
];
return merge(...changes).pipe(map((change) => {
connect(collectionViewer: CollectionViewer): Observable<DynamicFlatNode[]> {
return merge(collectionViewer.viewChange, this.treeControl.expansionModel.onChange!)
.pipe(map((change) => {
if ((change as SelectionChange<DynamicFlatNode>).added ||
(change as SelectionChange<DynamicFlatNode>).removed) {
this.handleTreeControl(change as SelectionChange<DynamicFlatNode>);
@@ -9,6 +9,7 @@
import {Component} from '@angular/core';
import {FlatTreeControl} from '@angular/cdk/tree';
import {MatTreeFlatDataSource, MatTreeFlattener} from '@angular/material/tree';
import {Observable} from 'rxjs/Observable';
import {LoadmoreNode, LoadmoreFlatNode, LoadmoreDatabase} from './loadmore-database';
const LOAD_MORE = 'LOAD_MORE';
@@ -50,7 +51,7 @@ export class LoadmoreTreeDemo {
database.initialize();
}
getChildren = (node: LoadmoreNode) => { return node.childrenChange; };
getChildren = (node: LoadmoreNode): Observable<LoadmoreNode[]> => { return node.childrenChange; };
transformer = (node: LoadmoreNode, level: number) => {
if (this.nodeMap.has(node.item)) {