@@ -79,9 +79,6 @@ export class CdkTree<V> {
7979 /** All CdkTreeItem instances within this tree. */
8080 private readonly _unorderedItems = signal ( new Set < CdkTreeItem < V > > ( ) ) ;
8181
82- /** All CdkGroup instances within this tree. */
83- readonly unorderedGroups = signal ( new Set < CdkTreeItemGroup < V > > ( ) ) ;
84-
8582 /** Orientation of the tree. */
8683 readonly orientation = input < 'vertical' | 'horizontal' > ( 'vertical' ) ;
8784
@@ -144,28 +141,14 @@ export class CdkTree<V> {
144141 this . _hasFocused . set ( true ) ;
145142 }
146143
147- register ( child : CdkTreeItemGroup < V > | CdkTreeItem < V > ) {
148- if ( child instanceof CdkTreeItemGroup ) {
149- this . unorderedGroups ( ) . add ( child ) ;
150- this . unorderedGroups . set ( new Set ( this . unorderedGroups ( ) ) ) ;
151- }
152-
153- if ( child instanceof CdkTreeItem ) {
154- this . _unorderedItems ( ) . add ( child ) ;
155- this . _unorderedItems . set ( new Set ( this . _unorderedItems ( ) ) ) ;
156- }
144+ register ( child : CdkTreeItem < V > ) {
145+ this . _unorderedItems ( ) . add ( child ) ;
146+ this . _unorderedItems . set ( new Set ( this . _unorderedItems ( ) ) ) ;
157147 }
158148
159- deregister ( child : CdkTreeItemGroup < V > | CdkTreeItem < V > ) {
160- if ( child instanceof CdkTreeItemGroup ) {
161- this . unorderedGroups ( ) . delete ( child ) ;
162- this . unorderedGroups . set ( new Set ( this . unorderedGroups ( ) ) ) ;
163- }
164-
165- if ( child instanceof CdkTreeItem ) {
166- this . _unorderedItems ( ) . delete ( child ) ;
167- this . _unorderedItems . set ( new Set ( this . _unorderedItems ( ) ) ) ;
168- }
149+ unregister ( child : CdkTreeItem < V > ) {
150+ this . _unorderedItems ( ) . delete ( child ) ;
151+ this . _unorderedItems . set ( new Set ( this . _unorderedItems ( ) ) ) ;
169152 }
170153}
171154
@@ -185,7 +168,7 @@ export class CdkTree<V> {
185168 '[attr.aria-current]' : 'pattern.current()' ,
186169 '[attr.aria-disabled]' : 'pattern.disabled()' ,
187170 '[attr.aria-level]' : 'pattern.level()' ,
188- '[attr.aria-owns]' : 'group()?.id ' ,
171+ '[attr.aria-owns]' : 'ownsId() ' ,
189172 '[attr.aria-setsize]' : 'pattern.setsize()' ,
190173 '[attr.aria-posinset]' : 'pattern.posinset()' ,
191174 '[attr.tabindex]' : 'pattern.tabindex()' ,
@@ -199,29 +182,21 @@ export class CdkTreeItem<V> implements OnInit, OnDestroy, HasElement {
199182 /** A unique identifier for the tree item. */
200183 private readonly _id = inject ( _IdGenerator ) . getId ( 'cdk-tree-item-' ) ;
201184
202- /** The top level CdkTree. */
203- private readonly _tree = inject ( CdkTree < V > ) ;
204-
205- /** The parent CdkTreeItem. */
206- private readonly _treeItem = inject ( CdkTreeItem < V > , { optional : true , skipSelf : true } ) ;
207-
208- /** The parent CdkGroup, if any. */
209- private readonly _parentGroup = inject ( CdkTreeItemGroup < V > , { optional : true } ) ;
185+ /** The owned tree item group. */
186+ private readonly _group = signal < CdkTreeItemGroup < V > | undefined > ( undefined ) ;
210187
211- /** The top level TreePattern. */
212- private readonly _treePattern = computed ( ( ) => this . _tree . pattern ) ;
213-
214- /** The parent TreeItemPattern. */
215- private readonly _parentPattern : Signal < TreeItemPattern < V > | TreePattern < V > > = computed (
216- ( ) => this . _treeItem ?. pattern ?? this . _treePattern ( ) ,
217- ) ;
188+ /** The id of the owned group. */
189+ readonly ownsId = computed ( ( ) => this . _group ( ) ?. id ) ;
218190
219191 /** The host native element. */
220192 readonly element = computed ( ( ) => this . _elementRef . nativeElement ) ;
221193
222194 /** The value of the tree item. */
223195 readonly value = input . required < V > ( ) ;
224196
197+ /** The parent tree root or tree item group. */
198+ readonly parent = input . required < CdkTree < V > | CdkTreeItemGroup < V > > ( ) ;
199+
225200 /** Whether the tree item is disabled. */
226201 readonly disabled = input ( false , { transform : booleanAttribute } ) ;
227202
@@ -231,46 +206,61 @@ export class CdkTreeItem<V> implements OnInit, OnDestroy, HasElement {
231206 /** Search term for typeahead. */
232207 readonly searchTerm = computed ( ( ) => this . label ( ) ?? this . element ( ) . textContent ) ;
233208
234- /** Manual group assignment. */
235- readonly group = signal < CdkTreeItemGroup < V > | undefined > ( undefined ) ;
209+ /** The tree root. */
210+ readonly tree : Signal < CdkTree < V > > = computed ( ( ) => {
211+ if ( this . parent ( ) instanceof CdkTree ) {
212+ return this . parent ( ) as CdkTree < V > ;
213+ }
214+ return ( this . parent ( ) as CdkTreeItemGroup < V > ) . ownedBy ( ) . tree ( ) ;
215+ } ) ;
236216
237217 /** The UI pattern for this item. */
238- readonly pattern : TreeItemPattern < V > = new TreeItemPattern < V > ( {
239- ...this ,
240- id : ( ) => this . _id ,
241- tree : this . _treePattern ,
242- parent : this . _parentPattern ,
243- children : computed (
244- ( ) =>
245- this . group ( )
246- ?. children ( )
247- . map ( item => ( item as CdkTreeItem < V > ) . pattern ) ?? [ ] ,
248- ) ,
249- hasChildren : computed ( ( ) => ! ! this . group ( ) ) ,
250- } ) ;
218+ pattern : TreeItemPattern < V > ;
251219
252220 constructor ( ) {
253- afterRenderEffect ( ( ) => {
254- const group = [ ...this . _tree . unorderedGroups ( ) ] . find ( group => group . value ( ) === this . value ( ) ) ;
255- if ( group ) {
256- this . group . set ( group ) ;
257- }
258- } ) ;
259-
260221 // Updates the visibility of the owned group.
261222 afterRenderEffect ( ( ) => {
262- this . group ( ) ?. visible . set ( this . pattern . expanded ( ) ) ;
223+ this . _group ( ) ?. visible . set ( this . pattern . expanded ( ) ) ;
263224 } ) ;
264225 }
265226
266227 ngOnInit ( ) {
267- this . _tree . register ( this ) ;
268- this . _parentGroup ?. register ( this ) ;
228+ this . parent ( ) . register ( this ) ;
229+ this . tree ( ) . register ( this ) ;
230+
231+ const treePattern = computed ( ( ) => this . tree ( ) . pattern ) ;
232+ const parentPattern = computed ( ( ) => {
233+ if ( this . parent ( ) instanceof CdkTree ) {
234+ return treePattern ( ) ;
235+ }
236+ return ( this . parent ( ) as CdkTreeItemGroup < V > ) . ownedBy ( ) . pattern ;
237+ } ) ;
238+ this . pattern = new TreeItemPattern < V > ( {
239+ ...this ,
240+ id : ( ) => this . _id ,
241+ tree : treePattern ,
242+ parent : parentPattern ,
243+ children : computed (
244+ ( ) =>
245+ this . _group ( )
246+ ?. children ( )
247+ . map ( item => ( item as CdkTreeItem < V > ) . pattern ) ?? [ ] ,
248+ ) ,
249+ hasChildren : computed ( ( ) => ! ! this . _group ( ) ) ,
250+ } ) ;
269251 }
270252
271253 ngOnDestroy ( ) {
272- this . _tree . deregister ( this ) ;
273- this . _parentGroup ?. deregister ( this ) ;
254+ this . parent ( ) . unregister ( this ) ;
255+ this . tree ( ) . unregister ( this ) ;
256+ }
257+
258+ register ( group : CdkTreeItemGroup < V > ) {
259+ this . _group . set ( group ) ;
260+ }
261+
262+ unregister ( ) {
263+ this . _group . set ( undefined ) ;
274264 }
275265}
276266
@@ -300,9 +290,6 @@ export class CdkTreeItemGroup<V> implements OnInit, OnDestroy, HasElement {
300290 /** The DeferredContentAware host directive. */
301291 private readonly _deferredContentAware = inject ( DeferredContentAware ) ;
302292
303- /** The top level CdkTree. */
304- private readonly _tree = inject ( CdkTree < V > ) ;
305-
306293 /** All groupable items that are descendants of the group. */
307294 private readonly _unorderedItems = signal ( new Set < CdkTreeItem < V > > ( ) ) ;
308295
@@ -318,8 +305,8 @@ export class CdkTreeItemGroup<V> implements OnInit, OnDestroy, HasElement {
318305 /** Child items within this group. */
319306 readonly children = computed ( ( ) => [ ...this . _unorderedItems ( ) ] . sort ( sortDirectives ) ) ;
320307
321- /** Identifier for matching the group owner . */
322- readonly value = input . required < V > ( ) ;
308+ /** Tree item that owns the group. */
309+ readonly ownedBy = input . required < CdkTreeItem < V > > ( ) ;
323310
324311 constructor ( ) {
325312 // Connect the group's hidden state to the DeferredContentAware's visibility.
@@ -329,19 +316,19 @@ export class CdkTreeItemGroup<V> implements OnInit, OnDestroy, HasElement {
329316 }
330317
331318 ngOnInit ( ) {
332- this . _tree . register ( this ) ;
319+ this . ownedBy ( ) . register ( this ) ;
333320 }
334321
335322 ngOnDestroy ( ) {
336- this . _tree . deregister ( this ) ;
323+ this . ownedBy ( ) . unregister ( ) ;
337324 }
338325
339326 register ( child : CdkTreeItem < V > ) {
340327 this . _unorderedItems ( ) . add ( child ) ;
341328 this . _unorderedItems . set ( new Set ( this . _unorderedItems ( ) ) ) ;
342329 }
343330
344- deregister ( child : CdkTreeItem < V > ) {
331+ unregister ( child : CdkTreeItem < V > ) {
345332 this . _unorderedItems ( ) . delete ( child ) ;
346333 this . _unorderedItems . set ( new Set ( this . _unorderedItems ( ) ) ) ;
347334 }
0 commit comments