我曾遇到同样的问题,通过重新思考实现方法解决了它。
我的情况是,当用户在最后一行使用tab键(失焦)时,我想把焦点放在该行(第一个输入框)上。我已经实现了一个指令来处理失焦并将焦点放在我的行上。
import { Directive, Input, Output, ElementRef, EventEmitter, HostListener, HostBinding } from '@angular/core';
@Directive({
selector: '[focusedRow]'
})
export class RowDirective {
static tabindex = 1;
static currentFocus = null;
private timer: any = null;
@HostBinding('tabindex') public tabIndex: number = 0;
@Input('formGroupName') public rowNumber: number;
@Output('focus') public onFocus: EventEmitter<number> = new EventEmitter<number>();
@Output('blur') public onBlur: EventEmitter<number> = new EventEmitter<number>();
constructor(private elm: ElementRef) {
this.tabIndex = RowDirective.tabindex++;
}
@HostListener('focusin', ['$event'])
public focusHandler(event: Event) {
if (RowDirective.currentFocus !== this) {
this.onFocus.emit(event);
RowDirective.currentFocus = this;
} else {
if (this.timer) {
window.clearTimeout(this.timer);
this.timer = null;
}
}
}
@HostListener('focusout', ['$event'])
public blurHandler(event: Event) {
this.timer = window.setTimeout(() => {
this.onBlur.emit(event);
if (RowDirective.currentFocus === this) {
RowDirective.currentFocus = null;
}
}, 200);
}
}
我所做的是,不再试图与Angular表单组进行对抗,而是当从响应式表单创建新行并添加该行时,因为表单行元素应用了
指令,更好的解决方案是在
指令初始化时简单地将焦点聚焦于该行(第一个输入)。
这是通过使用
OnInit
接口完成的。因此,上述代码已进行了调整以包括该接口(更改如下);
import { Directive, Input, Output, OnInit, ElementRef, EventEmitter, HostListener, HostBinding } from '@angular/core';
@Directive({
selector: '[focusedRow]'
})
export class RowDirective implements OnInit {
....
ngOnInit() {
this.elm.nativeElement.querySelector('input').focus();
}
....
}
所以创建以上指令,然后将该指令添加到您的表单数组元素中...
<tr *ngFor="let entry of myForms.controls; let index=index" [formGroupName]="index" focusedRow (focus)="rowFocus(index)" (blur)="rowBlur(index)">
这种方式可以在创建行时将焦点定位在第一个表单元素上。
这种解决方案的优美之处在于,当用户点击我的“添加新行”按钮时,它也能正常工作,并且您可以在[表格]行上获得一些很酷的焦点和失焦处理程序。(顺便说一下,这个秘密就是使用tabindex属性)。
希望这能帮助您的情况。