Reputation: 117
how to focus an invalid item in the form array,
Tried below with nativeElement focus , not getting exact invalid control.
if (this.basicForm.invalid) {
const invalid = [];
const controls = this.basicForm.controls;
for (const key of Object.keys(this.basicForm.controls)) {
if (this.basicForm.controls[key].invalid) {
const invalidControl =
this.el.nativeElement.querySelector('[formcontrolName="' + key + '"]');
invalidControl.focus();
break;
}
}
}
Upvotes: 0
Views: 346
Reputation: 57919
I'm afraid that you can not use .querySelector('[formcontrolName="' + key + '"]')
I suggest use a directive to focus the invalid field
@Directive({
selector: '[focusOnError]'
})
export class FocusOnErrorDirective {
@ContentChildren(NgControl, { descendants: true }) fields: QueryList<NgControl>
@HostListener('submit')
check() {
const fields = this.fields.toArray();
//here we can use
//console.log(field) to know how "reach" the nativeElement
for (let field of fields) {
if (field.invalid) {
const nativeElement = field.valueAccessor && (field.valueAccessor as any)._elementRef ?
(field.valueAccessor as any)._elementRef.nativeElement : null;
if (nativeElement) {
nativeElement.focus();
}
break;
}
}
}
}
Then, the only is adding the directive to the <form>
, e.g.
<form [formGroup]="form" focusOnError (submit)="submit(form)">
...
</form>
You can see an example in this stackblitz
Update if we has a complex element (a custom formControl, or, e.g. a ng-autocomplete from angular-ng-autocomplete) we need "reach" the nativeElement.
In the case of angular-ng-autocomplete, we "reach" the nativeElement using
(field.valueAccessor as any).searchInput.nativeElement
I discovered that you reach the nativeElement using console.log(field) and see in console the object
So, we can improve our directive take account this
check() {
const fields = this.fields.toArray();
for (let field of fields) {
if (field.invalid) {
const nativeElement =field.valueAccessor?
(field.valueAccessor as any)._elementRef?
(field.valueAccessor as any)._elementRef.nativeElement
: (field.valueAccessor as any).searchInput?
(field.valueAccessor as any).searchInput.nativeElement
: null:
null;
if (nativeElement) {
nativeElement.focus();
}
break;
}
}
}
see that first ask about field.valueAccessor, if exist ask about field.valueAccessor._elementRef if not exist ask about field.valueAccessor.searchInput if not exist the null
Upvotes: 2