在我的 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>
在我的TS文件下,我的表单配置如下:
this.addItemfForm = this.formBuilder.group({
libellePef: ['', Validators.required],
codeBasicat: ['', Validators.required ],
nomApplication: ['', Validators.required ],
urlCible: [''],
modeTransfert: [''],
});
我已经尝试过 autofocus 指令,但这没用
建议?
答案 0 :(得分:4)
“我的答案”的灵感来自yurzui的answer。我正在使用他的回答中的逻辑,通过使用特定的nativeElement
来获取特定FormControl
的{{1}}。
这是这样做的逻辑:
FormControl
现在,即使表单的错误字段无效,其错误字段也将为null。因此,要获取确切的第一个无效字段,我们必须遍历所有字段并检查每个字段的有效性。我可以在const originFormControlNameNgOnChanges = FormControlName.prototype.ngOnChanges;
FormControlName.prototype.ngOnChanges = function () {
const result = originFormControlNameNgOnChanges.apply(this, arguments);
this.control.nativeElement = this.valueAccessor._elementRef.nativeElement;
return result;
};
方法中编写此逻辑。像这样:
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
。
希望这可以为您解决问题。
这是您推荐的Working Sample StackBlitz。
答案 1 :(得分:2)
我使用指令来做到这一点。所以我的表单看起来像这样:
<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();
}
}
}
但是,此解决方案并不完整,因为有很多极端情况需要考虑。例如,如果第一个元素是单选按钮组,该怎么办。调度焦点事件将自动标记该字段。其次,并非每个角度广告ng-invalid都会被输入。
答案 2 :(得分:2)
我们只需在表单的commit()中编写此代码即可将重点放在第一个无效输入上。
if(this.form.invalid)
{
// Got focus to the error field
let invalidFields = [].slice.call(document.getElementsByClassName('ng-invalid'));
invalidFields[1].focus();
}
答案 3 :(得分:0)
该选项对我不起作用,但是我设法通过如下代码进行了更改来修复它:
@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();
}
}
}
答案 4 :(得分:0)
尝试一下:
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是否不是您自己遇到的形式,因此请正确查看它报告的第一个字段并将其放在正确的位置。
答案 5 :(得分:0)
在您的提交中使用以下代码。
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。
我们这里甚至不需要指令。