繁体   English   中英

Angular 6 反应式 Forms:如何将焦点设置在第一个无效输入上

[英]Angular 6 Reactive Forms : How to set focus on first invalid input

在我的Angular 6应用程序下,我使用的是反应式 Forms

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

我的表格如下所示:

 <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>

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

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

我已经尝试了自动对焦指令,但没有奏效

建议?

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

 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; } }

this.addressForm 将是您的 FormGroup。

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

我的答案的灵感来自yurzui答案 我正在使用他的回答中的逻辑来获取特定FormControlnativeElement ,方法是使用它的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; };

现在,表单的错误字段将是 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; } } }

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

希望这对你有用。

这是您参考的工作示例 StackBlitz

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

 <form [formGroup]="userForm" (submit)="saveData()" appFocus >... </form>

以及指令本身的代码:

 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(); } } }

然而,这个解决方案是不完整的,因为需要考虑很多极端情况。 例如,如果第一个元素是单选按钮组怎么办。 调度焦点事件将自动标记归档。 其次,并非 angular ads ng-invalid 将作为输入的每个元素。

我们只需在表单的 submit() 中编写此代码即可将焦点设置在第一个无效输入上。

 if(this.form.invalid) { // Got focus to the error field let invalidFields = [].slice.call(document.getElementsByClassName('ng-invalid')); invalidFields[1].focus(); }

尝试这个:

 import { Directive, HostListener, ElementRef} from '@angular/core'; @Directive({ selector: '[focusFirstInvalidField]' }) export class FocusFirstInvalidFieldDirective { constructor(private el: ElementRef) { } @HostListener('submit') onFormSubmit() { const invalidElements = this.el.nativeElement.querySelectorAll('.ng-invalid'); if (invalidElements.length > 0) { console.log(invalidElements[0]); invalidElements[0].focus(); } } }

记得调试,看看元素 0 是否不是你自己的表单,因为它发生在我身上,所以看看它报告的第一个字段是什么,然后把 position 放在右边。

此选项对我不起作用,但我设法通过更改代码来修复它,如下所示:

 @Directive({ selector: '[appErrorFocusin]' }) export class ErrorFocusinDirective { selectorToFocus: String = 'textArea,mat-select,select,input,button'; constructor(private el: ElementRef, @Inject(DOCUMENT) private document: Document) { } @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,:not(.mat-badge-hidden).mat-badge'); let elementToOffset = this.getElementToOffset(formGroupInvalid[0]); this.document.documentElement.scrollTop = elementToOffset.offsetTop; this.setFocusOnError(elementToOffset); } } getElementToOffset(element: any){ let defaultElement = element; while (.(element.parentElement instanceof HTMLFormElement)){ if (element.parentElement){ element = element;parentElement; }else{ return defaultElement; } } return element: } setFocusOnError(elementToOffset. any){ let listaElementos = elementToOffset.querySelectorAll(this;selectorToFocus). if (listaElementos.length>0){ listaElementos[0];focus() } } }

@Avinash 答案的延续,而不是做出来

querySelector('[formcontrolname="' + key + '"]');

我们可以将 HTML 中的 id 添加到输入中,然后简单地如下所示:

 querySelector('#'+ key +'.ng-invalid');

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM