I have a button that, when clicked, is replaced with an input field and a confirmation button, then when input is finished it's replaced with the original button again. When that happens, I want it to focus the original button after it appears (some users have requested better support for tab-navigation), but I can't seem to get it to do that consistently. The best I've been able to do is this:
// component.html
<button #durationButton *ngIf="!enteringDuration" (click)="enterDuration()">Enter Duration</button>
<ng-container *ngIf="enteringDuration">
<input type="number" [(ngModel)]="duration" (keyup.enter)="setDuration()">
<button (click)="setDuration()">✓</button>
</ng-container>
// component.ts
@ViewChild("durationButton") durationButton: ElementRef
duration: number
enteringDuration = false
shouldFocusDurationButton = false
ngAfterContentChecked () {
if (this.shouldFocusDurationButton && this.durationButton) {
this.shouldFocusDurationButton = false
this.durationButton.nativeElement.focus()
}
}
enterDuration () {
this.enteringDuration = true
}
setDuration () {
this.enteringDuration = false
this.shouldFocusDurationButton = true
}
If I click or press enter on the confirmation button, focus moves to the original button as soon as it appears, but if I press enter in the input field the button appears but for some reason it doesn't gain focus until I move the mouse. How do I make it work immediately for both?
You can use ViewChildren
and the QueryList.changes
event to be notified when the button is added to or removed from the view. If the QueryList
contains the button element, you can set the focus on it. See this stackblitz for a demo. Suggestion: you may want to do something similar to set the focus on the input field when it becomes visible.
import { Component, ViewChildren, ElementRef, AfterViewInit, QueryList } from '@angular/core';
...
export class AppComponent implements AfterViewInit {
@ViewChildren("durationButton") durationButton: QueryList<ElementRef>;
enteringDuration = false
ngAfterViewInit() {
this.setFocus(); // If the button is already present...
this.durationButton.changes.subscribe(() => {
this.setFocus();
});
}
setFocus() {
if (this.durationButton.length > 0) {
this.durationButton.first.nativeElement.focus();
}
}
enterDuration() {
this.enteringDuration = true
}
setDuration() {
this.enteringDuration = false
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With