Basil Jacob
Basil Jacob

Reputation: 117

How focus invalid item in form Array

enter image description here

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

Answers (1)

Eliseo
Eliseo

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

Related Questions