When loading a component, I want you to focus on the first element after initialization. I found a tutorial for this, but it doesn't want to work for me.
https://davidmcintosh.medium.com/auto-focusing-an-angular-input-the-easy-way-part-1-dcb1799e025f
But if I put it in a timer that is 0 then it works great. But I don't want to use timer.
ngAfterViewInit(): void {
timer(0).subscribe(() => this.firstElement.nativeElement.focus());
}
Why do I need a timer with such a ridiculous value?
Here is my HTML code:
<p class="news-title" tabindex="0" #firstElement>{{ 'news.title' | translate }}</p>
<ul class="news-list" role="list">
<li role="listitem" tabindex="0" class="list-item">{{ 'news.item-1' | translate }}</li>
<li role="listitem" tabindex="0" class="list-item">{{ 'news.item-2' | translate }}</li>
<li role="listitem" tabindex="0" class="list-item">{{ 'news.item-3' | translate }}</li>
</ul>
It is working for me, since your <p>
tag is static which would always be there, you can query viewChild
with {static: true}
, that case it would query the element before change detaction, see stackblitz.
@ViewChild('firstElement', {read: ElementRef, static: true})
firstElement?: ElementRef<unknown>;
ngAfterViewInit(): void {
(this.firstElement?.nativeElement as any).focus();
}
Better solution would be use material's A11y CDK cdkTrapFocusAutoCapture, see stackblitz
<p cdkTrapFocus="false" cdkTrapFocusAutoCapture class="news-title" tabindex="0" #firstElement>{{ 'news.title' }}</p>
<ul class="news-list" role="list">
<li role="listitem" tabindex="0" class="list-item">{{ 'news.item-1' }}</li>
<li role="listitem" tabindex="0" class="list-item">{{ 'news.item-2' }}</li>
<li role="listitem" tabindex="0" class="list-item">{{ 'news.item-3' }}</li>
</ul>
Note: