@@ -9,6 +9,7 @@ import {FocusableOption} from '@angular/cdk/a11y';
9
9
import { CollectionViewer , DataSource , isDataSource } from '@angular/cdk/collections' ;
10
10
import {
11
11
AfterContentChecked ,
12
+ AfterViewInit ,
12
13
ChangeDetectionStrategy ,
13
14
ChangeDetectorRef ,
14
15
Component ,
@@ -299,12 +300,11 @@ export class CdkTree<T> implements AfterContentChecked, CollectionViewer, OnDest
299
300
exportAs : 'cdkTreeNode' ,
300
301
host : {
301
302
'[attr.aria-expanded]' : 'isExpanded' ,
302
- '[attr.aria-level]' : 'level + 1' ,
303
303
'[attr.role]' : 'role' ,
304
304
'class' : 'cdk-tree-node' ,
305
305
} ,
306
306
} )
307
- export class CdkTreeNode < T > implements FocusableOption , OnDestroy {
307
+ export class CdkTreeNode < T > implements FocusableOption , OnDestroy , AfterViewInit {
308
308
/**
309
309
* The most recently created `CdkTreeNode`. We save it in static variable so we can retrieve it
310
310
* in `CdkTree` and set the data to it.
@@ -333,8 +333,11 @@ export class CdkTreeNode<T> implements FocusableOption, OnDestroy {
333
333
}
334
334
335
335
get level ( ) : number {
336
- return this . _tree . treeControl . getLevel ? this . _tree . treeControl . getLevel ( this . _data ) : 0 ;
337
- }
336
+ // Retrieve the aria-level of the parent node because level from treeControl is 0 indexed and
337
+ // aria-level is 1 indexed
338
+ return this . _tree . treeControl . getLevel ?
339
+ this . _tree . treeControl . getLevel ( this . _data ) : this . _parentNodeAriaLevel ( ) ;
340
+ }
338
341
339
342
/**
340
343
* The role of the node should always be 'treeitem'.
@@ -347,6 +350,10 @@ export class CdkTreeNode<T> implements FocusableOption, OnDestroy {
347
350
CdkTreeNode . mostRecentTreeNode = this as CdkTreeNode < T > ;
348
351
}
349
352
353
+ ngAfterViewInit ( ) : void {
354
+ this . _elementRef . nativeElement . setAttribute ( 'aria-level' , String ( this . level + 1 ) ) ;
355
+ }
356
+
350
357
ngOnDestroy ( ) {
351
358
// If this is the last tree node being destroyed,
352
359
// clear out the reference to avoid leaking memory.
@@ -371,4 +378,22 @@ export class CdkTreeNode<T> implements FocusableOption, OnDestroy {
371
378
}
372
379
this . role = 'treeitem' ;
373
380
}
381
+
382
+ private _parentNodeAriaLevel ( ) : number {
383
+ let parent = this . _elementRef . nativeElement . parentElement ;
384
+ while ( parent &&
385
+ ! ( parent . classList . contains ( 'cdk-nested-tree-node' ) || parent . classList . contains ( 'cdk-tree' ) ) ) {
386
+ parent = parent . parentElement ;
387
+ }
388
+ if ( ! parent ) {
389
+ throw Error ( 'Incorrect tree structure containing detached node.' ) ;
390
+ }
391
+ if ( parent . classList . contains ( 'cdk-nested-tree-node' ) ) {
392
+ return parseInt ( parent . getAttribute ( 'aria-level' ) ! ) ;
393
+ } else if ( parent . classList . contains ( 'cdk-tree' ) ) {
394
+ return 0 ;
395
+ } else {
396
+ throw Error ( `Incorrect tree structure containing ${ parent . className } .` ) ;
397
+ }
398
+ }
374
399
}
0 commit comments