I am making a data table component. For accessibility, I want each table header to have a tooltip via a title
attribute. The tooltip value can be explicitly set (in case it is different than the text in the header), but by default I want it to use whatever the inner text is.
I have a half-working solution, but it's not quite working and I don't know if I'm breaking some Angular rules by doing it this way.
Here's my abbreviated component html:
<div #headerContent [attr.title]="title"><ng-content></ng-content></div>
I am tagging the div with headerContent
so I can reference it later.
Ok, now here's the abbreviated component class:
@Component({ ... })
export class TableHeaderComponent implements AfterContentInit {
@ViewChild('headerContent') headerContent: ElementRef;
@Input() title: string;
ngAfterContentInit() {
if (!this.title) {
this.title = this.headerContent.nativeElement.textContent.trim();
}
}
}
The idea is that if no title
was specified, look at the div
and grab its text content, using that for the title
.
This works fine when I test it in the browser.
Example usage:
<th table-header>Contact</th>
Here, since I didn't specify a title
, it should use Contact
as the title
.
But when I write unit tests for this component, it blows up with:
Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'undefined'. Current value: 'Contact'
I'm not sure what I'm doing wrong here.
EDIT: Injecting the ChangeDetectorRef
into my component class and calling detectChanges()
after updating the title
property seems to have fixed the problem. It works in the browser and also the unit tests pass.
Still wondering if this is breaking any rules in Angular to do it this way.