Skip to content

Commit efbb7b7

Browse files
committed
comments explaining super life hook calls, add aria-expanded with setAttribute
1 parent 0251094 commit efbb7b7

File tree

5 files changed

+94
-10
lines changed

5 files changed

+94
-10
lines changed

src/cdk/tree/nested-node.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,11 @@ export class CdkNestedTreeNode<T> extends CdkTreeNode<T> implements AfterContent
5959
protected _differs: IterableDiffers) {
6060
super(_elementRef, _tree);
6161
// The classes are directly added here instead of in the host property because classes on
62-
// the host property are not inherited with View Engine.
63-
this._elementRef.nativeElement.classList.add('cdk-tree-node');
62+
// the host property are not inherited with View Engine. It is not set as a @HostBinding because
63+
// it is not set by the time it's children nodes try to read the class from it.
6464
this._elementRef.nativeElement.classList.add('cdk-nested-tree-node');
6565
}
6666

67-
ngOnInit() {
68-
super.ngOnInit();
69-
}
70-
7167
ngAfterContentInit() {
7268
this._dataDiffer = this._differs.find([]).create(this._tree.trackBy);
7369
if (!this._tree.treeControl.getChildren && (typeof ngDevMode === 'undefined' || ngDevMode)) {
@@ -84,6 +80,12 @@ export class CdkNestedTreeNode<T> extends CdkTreeNode<T> implements AfterContent
8480
.subscribe(() => this.updateChildrenNodes());
8581
}
8682

83+
// This is a workaround for https://github.com/angular/angular/issues/23091
84+
// In aot mode, the lifecycle hooks from parent class are not called.// Life cycle hooks in
85+
ngOnInit() {
86+
super.ngOnInit();
87+
}
88+
8789
ngOnDestroy() {
8890
this._clear();
8991
super.ngOnDestroy();

src/cdk/tree/tree.spec.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,23 @@ describe('CdkTree', () => {
129129
expect(ariaLevels).toEqual(['2', '3', '2', '2']);
130130
});
131131

132+
it('with the right aria-expanded attrs', () => {
133+
// add a child to the first node
134+
let data = dataSource.data;
135+
dataSource.addChild(data[2]);
136+
fixture.detectChanges();
137+
expect(getNodes(treeElement).every(node => {
138+
return node.getAttribute('aria-expanded') === 'false';
139+
})).toBe(true);
140+
141+
component.treeControl.expandAll();
142+
fixture.detectChanges();
143+
144+
expect(getNodes(treeElement).every(node => {
145+
return node.getAttribute('aria-expanded') === 'true';
146+
})).toBe(true);
147+
});
148+
132149
it('with the right data', () => {
133150
expect(dataSource.data.length).toBe(3);
134151

@@ -691,6 +708,24 @@ describe('CdkTree', () => {
691708
treeElement = fixture.nativeElement.querySelector('cdk-tree');
692709
});
693710

711+
it('with the right aria-expanded attrs', () => {
712+
expect(getNodes(treeElement).every(node => {
713+
return node.getAttribute('aria-expanded') === 'false';
714+
})).toBe(true);
715+
716+
component.toggleRecursively = false;
717+
let data = dataSource.data;
718+
const child = dataSource.addChild(data[1], false);
719+
dataSource.addChild(child, false);
720+
fixture.detectChanges();
721+
722+
(getNodes(treeElement)[1] as HTMLElement).click();
723+
fixture.detectChanges();
724+
725+
const ariaExpanded = getNodes(treeElement).map(n => n.getAttribute('aria-expanded'));
726+
expect(ariaExpanded).toEqual(['false', 'true', 'false', 'false']);
727+
});
728+
694729
it('should expand/collapse the node multiple times', () => {
695730
component.toggleRecursively = false;
696731
let data = dataSource.data;

src/cdk/tree/tree.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -341,10 +341,15 @@ export class CdkTreeNode<T> implements FocusableOption, OnDestroy, OnInit {
341341
protected _data: T;
342342

343343
// tslint:disable-next-line:no-host-decorator-in-concrete
344-
@HostBinding('attr.aria-expanded') get isExpanded(): boolean {
344+
@HostBinding('attr.aria-expanded')
345+
get isExpanded(): boolean {
345346
return this._tree.treeControl.isExpanded(this._data);
346347
}
347348

349+
set isExpanded(_expanded: boolean) {
350+
this._elementRef.nativeElement.setAttribute('aria-expanded', `${_expanded}`);
351+
}
352+
348353
get level(): number {
349354
// If the treeControl has a getLevel method, use it to get the level. Otherwise read the
350355
// aria-level off the parent node and use it as the level for this node (note aria-level is
@@ -357,8 +362,11 @@ export class CdkTreeNode<T> implements FocusableOption, OnDestroy, OnInit {
357362
protected _tree: CdkTree<T>) {
358363
CdkTreeNode.mostRecentTreeNode = this as CdkTreeNode<T>;
359364
// The classes are directly added here instead of in the host property because classes on
360-
// the host property are not inherited with View Engine.
365+
// the host property are not inherited with View Engine. It is not set as a @HostBinding because
366+
// it is not set by the time it's children nodes try to read the class from it.
361367
this._elementRef.nativeElement.classList.add('cdk-tree-node');
368+
this.role = 'treeitem';
369+
this.isExpanded = this.isExpanded;
362370
}
363371

364372
ngOnInit(): void {

src/material/tree/node.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,13 @@ export class MatTreeNode<T> extends _MatTreeNodeMixinBase<T>
5656

5757
this.tabIndex = Number(tabIndex) || 0;
5858
// The classes are directly added here instead of in the host property because classes on
59-
// the host property are not inherited with View Engine.
59+
// the host property are not inherited with View Engine. It is not set as a @HostBinding because
60+
// it is not set by the time it's children nodes try to read the class from it.
6061
this._elementRef.nativeElement.classList.add('mat-tree-node');
6162
}
6263

64+
// This is a workaround for https://github.com/angular/angular/issues/23091
65+
// In aot mode, the lifecycle hooks from parent class are not called.
6366
ngOnInit() {
6467
super.ngOnInit();
6568
}
@@ -124,7 +127,8 @@ export class MatNestedTreeNode<T> extends CdkNestedTreeNode<T> implements AfterC
124127
super(_elementRef, _tree, _differs);
125128
this.tabIndex = Number(tabIndex) || 0;
126129
// The classes are directly added here instead of in the host property because classes on
127-
// the host property are not inherited with View Engine.
130+
// the host property are not inherited with View Engine. It is not set as a @HostBinding because
131+
// it is not set by the time it's children nodes try to read the class from it.
128132
this._elementRef.nativeElement.classList.add('mat-nested-tree-node');
129133
}
130134

src/material/tree/tree.spec.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,23 @@ describe('MatTree', () => {
7575
expect(ariaLevels).toEqual(['1', '1', '1', '2']);
7676
});
7777

78+
it('with the right aria-expanded attrs', () => {
79+
// add a child to the first node
80+
let data = underlyingDataSource.data;
81+
underlyingDataSource.addChild(data[2]);
82+
fixture.detectChanges();
83+
expect(getNodes(treeElement).every(node => {
84+
return node.getAttribute('aria-expanded') === 'false';
85+
})).toBe(true);
86+
87+
component.treeControl.expandAll();
88+
fixture.detectChanges();
89+
90+
expect(getNodes(treeElement).every(node => {
91+
return node.getAttribute('aria-expanded') === 'true';
92+
})).toBe(true);
93+
});
94+
7895
it('with the right data', () => {
7996
expect(underlyingDataSource.data.length).toBe(3);
8097

@@ -404,6 +421,24 @@ describe('MatTree', () => {
404421
fixture.detectChanges();
405422
});
406423

424+
it('with the right aria-expanded attrs', () => {
425+
expect(getNodes(treeElement).every(node => {
426+
return node.getAttribute('aria-expanded') === 'false';
427+
})).toBe(true);
428+
429+
component.toggleRecursively = false;
430+
let data = underlyingDataSource.data;
431+
const child = underlyingDataSource.addChild(data[1]);
432+
underlyingDataSource.addChild(child);
433+
fixture.detectChanges();
434+
435+
(getNodes(treeElement)[1] as HTMLElement).click();
436+
fixture.detectChanges();
437+
438+
const ariaExpanded = getNodes(treeElement).map(n => n.getAttribute('aria-expanded'));
439+
expect(ariaExpanded).toEqual(['false', 'true', 'false', 'false']);
440+
});
441+
407442
it('should expand/collapse the node', () => {
408443
component.toggleRecursively = false;
409444
let data = underlyingDataSource.data;

0 commit comments

Comments
 (0)