Angular 6反应形式:如何将重点放在第一个无效输入上

fir*_*baa 7 javascript html5 rxjs angular angular-reactive-forms

Angular 6应用程序下,我正在使用反应式表单

我的目的是在提交时,我想将重点放在出现错误时的第一个无效输入上。

我的表格如下所示:

<form [formGroup]="addItemfForm " (ngSubmit)="onSubmitForm()">

        <div class="form-inline form-group">
          <label class="col-md-2 justify-content-start">
            Libellé du pef
            <span class="startRequired mr-1"> *</span>
          </label>
          <input type="text"
                 maxlength="100"
                 formControlName="libellePef"
                 class="col-md-6 form-control"
                 placeholder="saisie obligatoire"
                 [ngClass]="{ 'is-invalid': submitted && formFiels.libellePef.errors }"/>
          <div *ngIf="submitted && formFiels.libellePef.errors" class="col invalid-feedback">
            <div class="col text-left" *ngIf="formFiels.libellePef.errors.required">Libellé du pef est requis.</div>
          </div>
        </div>

        <div class="form-inline form-group">
          <label class="col-md-2 justify-content-start">
            Code Basicat
            <span class="startRequired mr-1"> *</span>
          </label>
          <input type="text"
                 maxlength="100"
                 formControlName="codeBasicat"
                 class="col-md-3 form-control"
                 placeholder="saisie obligatoire"
                 [ngClass]="{ 'is-invalid': submitted && formFiels.codeBasicat.errors }"/>
          <div *ngIf="submitted && formFiels.codeBasicat.errors" class="col invalid-feedback">
            <div class="text-left" *ngIf="formFiels.codeBasicat.errors.required">Code Basicat est requis.</div>
          </div>
        </div>

        <div class="form-inline form-group">
          <label class="col-md-2 justify-content-start">
            Nom de l'application
            <span class="startRequired mr-1"> *</span>
          </label>
          <input type="text"
                 maxlength="100"
                 formControlName="nomApplication"
                 class="col-md-6 form-control"
                 placeholder="saisie obligatoire"
                 [ngClass]="{ 'is-invalid': submitted && formFiels.nomApplication.errors }"/>
          <div *ngIf="submitted && formFiels.nomApplication.errors" class="col invalid-feedback">
            <div class="text-left" *ngIf="formFiels.nomApplication.errors.required">Nom de l'application est requis.
            </div>
          </div>
        </div>
</form>
Run Code Online (Sandbox Code Playgroud)

在我的TS文件下,我的表单配置如下所示:

this.addItemfForm = this.formBuilder.group({
  libellePef: ['', Validators.required],
  codeBasicat: ['', Validators.required ],
  nomApplication: ['', Validators.required ],
  urlCible: [''],
  modeTransfert: [''],
});
Run Code Online (Sandbox Code Playgroud)

我已经尝试过自动对焦指令,但这没有用

有什么建议吗?

小智 21

在您的提交中使用以下代码。

for (const key of Object.keys(this.addressForm.controls)) {
      if (this.addressForm.controls[key].invalid) {
        const invalidControl = this.el.nativeElement.querySelector('[formcontrolname="' + key + '"]');
        invalidControl.focus();
        break;
     }
}
Run Code Online (Sandbox Code Playgroud)

this.addressForm 将是您的 FormGroup。

我们甚至不需要这里的指令。

  • 将“private el: ElementRef”添加到您的构造函数中(ElementRef 形式“@angular/core”) (3认同)

Sid*_*era 5

我的答案的灵感来自yurzui答案。我正在使用他的回答中的逻辑来通过使用来获取nativeElement特定FormControl内容FormControl

这是这样做的逻辑:

const originFormControlNameNgOnChanges = FormControlName.prototype.ngOnChanges;
FormControlName.prototype.ngOnChanges = function () {
  const result = originFormControlNameNgOnChanges.apply(this, arguments);
  this.control.nativeElement = this.valueAccessor._elementRef.nativeElement;
  return result;
};
Run Code Online (Sandbox Code Playgroud)

现在,即使表单的错误字段无效,该字段也将为null。因此,要获取确切的第一个无效字段,我们必须遍历所有字段并检查每个字段的有效性。我可以在onSubmitForm()方法中编写此逻辑。像这样:

onSubmitForm() {
  const fieldsToCheck = [
    'codeBasicat',
    'libellePef',
    'nomApplication'
  ];
  for (let i = 0; i < fieldsToCheck.length; i++) {
    const fieldName = fieldsToCheck[i];
    if (this.addItemfForm.get(fieldName).invalid) {
      ( < any > this.addItemfForm.get(fieldName)).nativeElement.focus();
      break;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

我故意使用for而不是Array.forEach因为我想摆脱循环。

希望这可以为您解决问题。

这是供您参考的工作样本StackBlitz


pio*_*cki 5

我使用指令做到了这一点。所以我的表格看起来像这样:

<form [formGroup]="userForm" (submit)="saveData()" appFocus >
...
</form>
Run Code Online (Sandbox Code Playgroud)

以及指令本身的代码:

import { Directive, HostListener, Input, ElementRef } from '@angular/core';
import { NgForm } from '@angular/forms';

@Directive({
  selector: '[appFocus]'
})
export class FocusDirective {

  constructor(private el: ElementRef) { }

  @Input() formGroup: NgForm;

  @HostListener('submit', ['$event'])
  public onSubmit(event): void {
    if ('INVALID' === this.formGroup.status) {
      event.preventDefault();

      const formGroupInvalid = this.el.nativeElement.querySelectorAll('.ng-invalid');
      (<HTMLInputElement>formGroupInvalid[0]).focus();
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

然而,这个解决方案并不完整,因为必须考虑很多极端情况。例如,如果第一个元素是单选按钮组怎么办?调度焦点事件会自动标记该字段。其次,并非 Angular ads ng-invalid 的每个元素都将成为输入。