Skip to content

Commit 07f2d7c

Browse files
committed
refactor(cdk/tree): signalify _flattenedNodes
1 parent 7f05567 commit 07f2d7c

File tree

1 file changed

+30
-20
lines changed

1 file changed

+30
-20
lines changed

src/cdk/tree/tree.ts

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import {
4141
Output,
4242
QueryList,
4343
TrackByFunction,
44+
computed,
4445
signal,
4546
effect,
4647
ViewChild,
@@ -50,7 +51,7 @@ import {
5051
inject,
5152
booleanAttribute,
5253
} from '@angular/core';
53-
import {toSignal} from '@angular/core/rxjs-interop';
54+
import {toObservable, toSignal} from '@angular/core/rxjs-interop';
5455
import {coerceObservable} from '@angular/cdk/coercion/private';
5556
import {
5657
BehaviorSubject,
@@ -85,6 +86,7 @@ import {
8586
getTreeMultipleDefaultNodeDefsError,
8687
getTreeNoValidDataSourceError,
8788
} from './tree-errors';
89+
import { NgTemplateOutlet } from '@angular/common';
8890

8991
type RenderingData<T> =
9092
| {
@@ -105,7 +107,16 @@ type RenderingData<T> =
105107
@Component({
106108
selector: 'cdk-tree',
107109
exportAs: 'cdkTree',
108-
template: `<ng-container cdkTreeNodeOutlet></ng-container>`,
110+
template: `
111+
<ng-template let-nodes>
112+
@for (node of nodes(); track node.key) {
113+
<ng-container
114+
[ngTemplateOutlet]="node.template"
115+
[ngTemplateOutletContext]="node.context" />
116+
}
117+
</ng-template>
118+
<ng-container cdkTreeNodeOutlet></ng-container>
119+
`,
109120
host: {
110121
'class': 'cdk-tree',
111122
'role': 'tree',
@@ -118,7 +129,7 @@ type RenderingData<T> =
118129
// tslint:disable-next-line:validate-decorators
119130
changeDetection: ChangeDetectionStrategy.Default,
120131
standalone: true,
121-
imports: [CdkTreeNodeOutlet],
132+
imports: [CdkTreeNodeOutlet, NgTemplateOutlet],
122133
})
123134
export class CdkTree<T, K = T>
124135
implements
@@ -261,13 +272,6 @@ export class CdkTree<T, K = T>
261272
/** Keep track of which nodes are expanded. */
262273
private _expansionModel?: SelectionModel<K>;
263274

264-
/**
265-
* Maintain a synchronous cache of flattened data nodes. This will only be
266-
* populated after initial render, and in certain cases, will be delayed due to
267-
* relying on Observable `getChildren` calls.
268-
*/
269-
private _flattenedNodes: BehaviorSubject<readonly T[]> = new BehaviorSubject<readonly T[]>([]);
270-
271275
/** The automatically determined node type for the tree. */
272276
private _nodeType = new BehaviorSubject<'flat' | 'nested' | null>(null);
273277

@@ -297,6 +301,18 @@ export class CdkTree<T, K = T>
297301
),
298302
{initialValue: null},
299303
);
304+
/**
305+
* Maintain a synchronous cache of flattened data nodes. This will only be
306+
* populated after initial render, and in certain cases, will be delayed due to
307+
* relying on Observable `getChildren` calls.
308+
*/
309+
private readonly _flattenedNodes = computed(() => {
310+
return this._renderData()?.flattenedNodes ?? [];
311+
});
312+
private readonly _flatNodesObs = toObservable(this._flattenedNodes);
313+
private readonly _renderNodes = computed(() => {
314+
return this._renderData()?.renderNodes ?? [];
315+
});
300316

301317
constructor(...args: unknown[]);
302318
constructor() {
@@ -404,7 +420,6 @@ export class CdkTree<T, K = T>
404420

405421
// If we're here, then we know what our node type is, and therefore can
406422
// perform our usual rendering pipeline.
407-
this._updateCachedData(data.flattenedNodes);
408423
this.renderNodeChanges(data.renderNodes);
409424
this._updateKeyManagerItems(data.flattenedNodes);
410425
// Explicitly detect the initial set of changes to this component subtree
@@ -686,7 +701,7 @@ export class CdkTree<T, K = T>
686701
} else if (this._expansionModel) {
687702
const expansionModel = this._expansionModel;
688703
expansionModel.select(
689-
...this._flattenedNodes.value.map(child => this._getExpansionKey(child)),
704+
...this._flattenedNodes().map(child => this._getExpansionKey(child)),
690705
);
691706
}
692707
}
@@ -698,7 +713,7 @@ export class CdkTree<T, K = T>
698713
} else if (this._expansionModel) {
699714
const expansionModel = this._expansionModel;
700715
expansionModel.deselect(
701-
...this._flattenedNodes.value.map(child => this._getExpansionKey(child)),
716+
...this._flattenedNodes().map(child => this._getExpansionKey(child)),
702717
);
703718
}
704719
}
@@ -739,15 +754,14 @@ export class CdkTree<T, K = T>
739754
);
740755

741756
if (levelAccessor) {
742-
return combineLatest([isExpanded, this._flattenedNodes]).pipe(
757+
return combineLatest([isExpanded, this._flatNodesObs]).pipe(
743758
map(([expanded, flattenedNodes]) => {
744759
if (!expanded) {
745760
return [];
746761
}
747762
return this._findChildrenByLevel(
748763
levelAccessor,
749764
flattenedNodes,
750-
751765
dataNode,
752766
1,
753767
);
@@ -878,7 +892,7 @@ export class CdkTree<T, K = T>
878892
if (this.levelAccessor) {
879893
const results = this._findChildrenByLevel(
880894
this.levelAccessor,
881-
this._flattenedNodes.value,
895+
this._flattenedNodes(),
882896
dataNode,
883897
Infinity,
884898
);
@@ -1083,10 +1097,6 @@ export class CdkTree<T, K = T>
10831097
}
10841098
}
10851099

1086-
private _updateCachedData(flattenedNodes: readonly T[]) {
1087-
this._flattenedNodes.next(flattenedNodes);
1088-
}
1089-
10901100
private _updateKeyManagerItems(flattenedNodes: readonly T[]) {
10911101
this._keyManagerNodes.next(flattenedNodes);
10921102
}

0 commit comments

Comments
 (0)