通过 ngIf 在元素出现后聚焦它
Focus an element after it appears via ngIf
我有一个按钮,单击该按钮时,它会被一个输入字段和一个确认按钮替换,然后当输入完成后,它又会被原来的按钮替换。当发生这种情况时,我希望它在原始按钮出现后聚焦(一些用户要求更好地支持选项卡导航),但我似乎无法让它始终如一地做到这一点。我能做的最好的是:
// 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
}
如果我在确认按钮上单击或按 enter,焦点会在它出现时立即移动到原始按钮,但如果我在输入字段中按 enter,按钮会出现,但由于某种原因它没有获得焦点直到我移动鼠标。如何让它立即对两者起作用?
是的,*ngIf 和 ViewChild 不能一起玩。我上了一门关于 ViewChild 的课程,并做了一整节只是关于处理 *ngIf。
一种选择是使用隐藏属性而不是 *ngIf。
另一种选择是绑定到 setter(类似于绑定到函数的方式):
您可以使用 ViewChildren
和 QueryList.changes
事件在按钮添加到视图或从视图中删除时收到通知。如果 QueryList
包含按钮元素,您可以将焦点设置在它上面。有关演示,请参阅 this stackblitz。建议:您可能想做一些类似的事情,以便在输入字段可见时将焦点设置在输入字段上。
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
}
}
我有一个按钮,单击该按钮时,它会被一个输入字段和一个确认按钮替换,然后当输入完成后,它又会被原来的按钮替换。当发生这种情况时,我希望它在原始按钮出现后聚焦(一些用户要求更好地支持选项卡导航),但我似乎无法让它始终如一地做到这一点。我能做的最好的是:
// 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
}
如果我在确认按钮上单击或按 enter,焦点会在它出现时立即移动到原始按钮,但如果我在输入字段中按 enter,按钮会出现,但由于某种原因它没有获得焦点直到我移动鼠标。如何让它立即对两者起作用?
是的,*ngIf 和 ViewChild 不能一起玩。我上了一门关于 ViewChild 的课程,并做了一整节只是关于处理 *ngIf。
一种选择是使用隐藏属性而不是 *ngIf。
另一种选择是绑定到 setter(类似于绑定到函数的方式):
您可以使用 ViewChildren
和 QueryList.changes
事件在按钮添加到视图或从视图中删除时收到通知。如果 QueryList
包含按钮元素,您可以将焦点设置在它上面。有关演示,请参阅 this stackblitz。建议:您可能想做一些类似的事情,以便在输入字段可见时将焦点设置在输入字段上。
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
}
}