Angular,如何在FormArray的特定FormControl中设置焦点

6

如何将焦点设置到表单数组中的特定字段?

这是表单数组:

    this.productForm = this.formBuilder.array([
     this.formBuilder.group({
     code: [null],
     description: [null],
     unitPrice: [null],
     qty: [null],
     discount: [null],
     vat: [null],
     total: [null],
     amount: [null],
     taxAmount: [null]
  })
]);

我可以有很多这样的表格组(formGroup),但我需要专注一个特定的描述字段(description field)。在 Angular 中有没有聪明的方法?


FormBuilder API没有详细的说明:https://angular.io/api/forms/FormBuilder - Maihan Nijat
3个回答

3

如果您知道要重点关注的特定项目,首先可以通过添加模板引用来简化操作:

<input
  #fieldName
  type="text"
  id="fieldName"
  name="fieldName"
  formControlName="yourFieldName" />

然后在您的组件中(可能在ngAfterViewInit()方法中):
@ViewChild('fieldName') fieldName: ElementRef;

接下来,要集中注意力在您的元素上:
this.fieldName.nativeElement.focus();

NB:这种方法容易受到XSS攻击。

1
好的,但在我的情况下,引用是多个的,因为它是一个formArray的元素,所以我无法引用特定的元素。 - Alessandro Celeghin
1
如果您知道您想要的元素,并且您控制模板本身,您可以将其制作成以您想要的方式编写id/name,这样您就可以通过组件访问它。 - rrd

0
你可能想在你的应用程序中使用angular2-focus包,以便从下面的位置进行一致的使用。你将能够在应用程序的任何地方重复使用这段代码。

https://www.npmjs.com/package/angular2-focus

使用这个包,您将能够像下面这样聚焦任何输入元素。
<input type="text" focus="true">

请按照以下方式包含模块

import {NgModule, Component} from '@angular/core';
import {FocusModule} from 'angular2-focus';
@NgModule({
  imports: [FocusModule.forRoot()],
  declarations: [AppComponent],
  bootstrap: [AppComponent]
})
export class AppModule { }

0

我曾遇到同样的问题,通过重新思考实现方法解决了它。

我的情况是,当用户在最后一行使用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) {
    // When we're not the current focus.
    if (RowDirective.currentFocus !== this) {
      this.onFocus.emit(event);

      RowDirective.currentFocus = this;

    } else {
      // Stop our blur from happening since it's the same row
      if (this.timer) {
        window.clearTimeout(this.timer);
        this.timer = null;
      }
    }
  }
  @HostListener('focusout', ['$event'])
  public blurHandler(event: Event) {
    this.timer = window.setTimeout(() => {
      // If our row has changed, then we have blurred.
      this.onBlur.emit(event);

      // Clear if this is still listed as the Focused Row.
      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() {
    // Focus on the first Form Element
    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属性)。
希望这能帮助您的情况。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接