mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
fix(tree): fix type error in tree (#10095)
This commit is contained in:
committed by
Joey Perrott
parent
19463bb6c9
commit
6d94aec797
@@ -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) {
|
||||
|
||||
@@ -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>;
|
||||
}
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
Reference in New Issue
Block a user