Skip to content

Commit 10d85e9

Browse files
committed
fix(tree): improve nested tree node & fix nested tree control
1 parent c28549d commit 10d85e9

File tree

4 files changed

+31
-25
lines changed

4 files changed

+31
-25
lines changed

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,17 @@ export class NestedTreeControl<T> extends BaseTreeControl<T> {
2626
expandAll(): void {
2727
this.expansionModel.clear();
2828
let toBeExpanded = <any>[];
29-
this.dataNodes.forEach(dataNode => toBeExpanded.push(...this.getDescendants(dataNode)));
29+
this.dataNodes.forEach(dataNode =>
30+
toBeExpanded.push(...this.getDescendants(dataNode), dataNode));
3031
this.expansionModel.select(...toBeExpanded);
3132
}
3233

3334
/** Gets a list of descendant dataNodes of a subtree rooted at given data node recursively. */
3435
getDescendants(dataNode: T): T[] {
3536
const descendants = [];
3637
this._getDescendants(descendants, dataNode);
37-
return descendants;
38+
// Remove the node itself
39+
return descendants.slice(1);
3840
}
3941

4042
/** A helper function to get descendants recursively. */

src/cdk/tree/nested-node.ts

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ import {
1010
ContentChildren,
1111
Directive,
1212
ElementRef,
13+
IterableDiffers,
14+
IterableDiffer,
15+
IterableChangeRecord,
1316
OnDestroy,
1417
QueryList,
1518
} from '@angular/core';
@@ -51,32 +54,33 @@ import {getTreeControlFunctionsMissingError} from './tree-errors';
5154
providers: [{provide: CdkTreeNode, useExisting: CdkNestedTreeNode}]
5255
})
5356
export class CdkNestedTreeNode<T> extends CdkTreeNode<T> implements AfterContentInit, OnDestroy {
57+
/** Differ used to find the changes in the data provided by the data source. */
58+
private _dataDiffer: IterableDiffer<T>;
59+
5460
/** The children data dataNodes of current node. They will be placed in `CdkTreeNodeOutlet`. */
5561
protected _children: T[];
5662

5763
/** The children node placeholder. */
5864
@ContentChildren(CdkTreeNodeOutlet) nodeOutlet: QueryList<CdkTreeNodeOutlet>;
5965

6066
constructor(protected _elementRef: ElementRef,
61-
protected _tree: CdkTree<T>) {
67+
protected _tree: CdkTree<T>,
68+
protected _differs: IterableDiffers) {
6269
super(_elementRef, _tree);
6370
}
6471

6572
ngAfterContentInit() {
73+
this._dataDiffer = this._differs.find([]).create();
6674
if (!this._tree.treeControl.getChildren) {
6775
throw getTreeControlFunctionsMissingError();
6876
}
6977
this._tree.treeControl.getChildren(this.data).pipe(takeUntil(this._destroyed))
7078
.subscribe(result => {
71-
if (result && result.length) {
72-
// In case when nodeOutlet is not in the DOM when children changes, save it in the node
73-
// and add to nodeOutlet when it's available.
74-
this._children = result as T[];
75-
this._addChildrenNodes();
76-
}
79+
this._children = result;
80+
this._updateChildrenNodes();
7781
});
7882
this.nodeOutlet.changes.pipe(takeUntil(this._destroyed))
79-
.subscribe((_) => this._addChildrenNodes());
83+
.subscribe((_) => this._updateChildrenNodes());
8084
}
8185

8286
ngOnDestroy() {
@@ -86,12 +90,10 @@ export class CdkNestedTreeNode<T> extends CdkTreeNode<T> implements AfterContent
8690
}
8791

8892
/** Add children dataNodes to the NodeOutlet */
89-
protected _addChildrenNodes(): void {
90-
this._clear();
91-
if (this.nodeOutlet.length && this._children && this._children.length) {
92-
this._children.forEach((child, index) => {
93-
this._tree.insertNode(child, index, this.nodeOutlet.first.viewContainer);
94-
});
93+
protected _updateChildrenNodes(): void {
94+
if (this.nodeOutlet.length && this._children) {
95+
const viewContainer = this.nodeOutlet.first.viewContainer;
96+
this._tree.renderNodeChanges(this._children, this._dataDiffer, viewContainer);
9597
}
9698
}
9799

src/cdk/tree/tree.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -263,27 +263,27 @@ export class CdkTree<T> implements CollectionViewer, OnInit, OnDestroy {
263263

264264
if (dataStream) {
265265
this._dataSubscription = dataStream.pipe(takeUntil(this._onDestroy))
266-
.subscribe(data => this._renderNodeChanges(data));
266+
.subscribe(data => this.renderNodeChanges(data));
267267
} else {
268268
throw getTreeNoValidDataSourceError();
269269
}
270270
}
271271

272272
/** Check for changes made in the data and render each change (node added/removed/moved). */
273-
private _renderNodeChanges(dataNodes: T[]) {
274-
const changes = this._dataDiffer.diff(dataNodes);
273+
renderNodeChanges(data: T[], dataDiffer?: IterableDiffer<T>, viewContainer?: ViewContainerRef) {
274+
const changes = (dataDiffer ? dataDiffer : this._dataDiffer).diff(data);
275275
if (!changes) { return; }
276276

277-
const viewContainer = this._nodeOutlet.viewContainer;
277+
const container = viewContainer ? viewContainer : this._nodeOutlet.viewContainer;
278278
changes.forEachOperation(
279279
(item: IterableChangeRecord<T>, adjustedPreviousIndex: number, currentIndex: number) => {
280280
if (item.previousIndex == null) {
281-
this.insertNode(dataNodes[currentIndex], currentIndex);
281+
this.insertNode(data[currentIndex], currentIndex, container);
282282
} else if (currentIndex == null) {
283-
viewContainer.remove(adjustedPreviousIndex);
283+
container.remove(adjustedPreviousIndex);
284284
} else {
285-
const view = viewContainer.get(adjustedPreviousIndex);
286-
viewContainer.move(view!, currentIndex);
285+
const view = container.get(adjustedPreviousIndex);
286+
container.move(view!, currentIndex);
287287
}
288288
});
289289
}

src/lib/tree/node.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
Directive,
1313
ElementRef,
1414
Input,
15+
IterableDiffers,
1516
QueryList
1617
} from '@angular/core';
1718
import {
@@ -94,8 +95,9 @@ export class MatNestedTreeNode<T> extends _MatNestedTreeNodeMixinBase<T>
9495

9596
constructor(protected _elementRef: ElementRef,
9697
protected _tree: CdkTree<T>,
98+
protected _differs: IterableDiffers,
9799
@Attribute('tabindex') tabIndex: string) {
98-
super(_elementRef, _tree);
100+
super(_elementRef, _tree, _differs);
99101

100102
this.tabIndex = Number(tabIndex) || 0;
101103
}

0 commit comments

Comments
 (0)