Angular 2 Focus on first invalid input after Click/Event

前端 未结 9 1706
不思量自难忘°
不思量自难忘° 2021-02-04 03:46

I have an odd requirement and was hoping for some help.

I need to focus on the first found invalid input of a form after clicking a button (not submit). The form is rath

相关标签:
9条回答
  • 2021-02-04 04:28

    For Angular Material , The below worked for me

    @ViewChildren(MatInput) inputs: QueryList <MatInput>;
    this.inputs.find(input => !input.ngControl.valid).focus();
    
    0 讨论(0)
  • 2021-02-04 04:29
      @HostListener('submit', ['$event'])
      onSubmit(event) {
        event.preventDefault();
          if (!this.checkoutForm.valid) {
            let target;
            target = $('input[type=text].ng-invalid').first();
            if (target) {
                $('html,body').animate({ scrollTop: $(target).offset().top }, 'slow', ()=> {
                  target.focus();
                });
            }
          }
       }
    
    0 讨论(0)
  • 2021-02-04 04:30

    If you are using AngularMaterial, the MdInputDirective has a focus() method which allow you to directly focus on the input field.

    In your component, just get a reference to all the inputs with the @ViewChildren annotation, like this:

    @ViewChildren(MdInputDirective) inputs: QueryList<MdInputDirective>;

    Then, setting focus on the first invalid input is as simple as this:

    this.inputs.find(input => !input._ngControl.valid).focus()

    0 讨论(0)
  • 2021-02-04 04:31

    Plain HTML solution. If you don't need to be scrolling , just focus on first valid input, I use :

    public submitForm() {
        if(this.form.valid){
            // submit form
        } else {
            let invalidFields = [].slice.call(document.getElementsByClassName('ng-invalid'));
            invalidFields[1].focus();
        }
    }
    

    This is for template driven form here. We focus on second element of invalidFields cuz first is the whole form which is invalid too.

    0 讨论(0)
  • 2021-02-04 04:38

    I don't know if this is valid approach or not but this is working great for me.

    import { Directive, Input, HostListener, ElementRef } from '@angular/core';
    import { NgForm } from '@angular/forms';
    import * as $ from 'jquery';
    
    @Directive({ selector: '[accessible-form]' })
    export class AccessibleForm {
    
        @Input('form') form: NgForm;
    
        constructor(private el: ElementRef) {
    
        }
    
        @HostListener('submit', ['$event'])
        onSubmit(event) {
            event.preventDefault();
    
            if (!this.form.valid) {
                let target;
    
                target = this.el.nativeElement.querySelector('.ng-invalid')
    
                if (target) {
                    $('html,body').animate({ scrollTop: $(target).offset().top }, 'slow');
                    target.focus();
                }
            }
        }
    
    }
    

    In HTML

    <form [formGroup]="addUserForm" class="form mt-30" (ngSubmit)="updateUser(addUserForm)" accessible-form [form]="addUserForm"></form>
    

    I have mixed the approach of angularjs accessible form directive in this. Improvements are welcomed!!!

    0 讨论(0)
  • This works for me. Not the most elegant solution, but given the constraints in Angular we are all experiencing for this particular task, it does the job.

    scrollTo(el: Element): void {
       if(el) { 
        el.scrollIntoView({ behavior: 'smooth' });
       }
    }
    
    scrollToError(): void {
       const firstElementWithError = document.querySelector('.ng-invalid');
       this.scrollTo(firstElementWithError);
    }
    
    async scrollIfFormHasErrors(form: FormGroup): Promise <any> {
      await form.invalid;
      this.scrollToError();
    }
    

    This works, allowing you to evade manipulating the DOM. It simply goes to the first element with .ng-invalid on the page through the document.querySelector() which returns the first element in the returned list.

    To use it:

    this.scrollIfFormHasErrors(this.form).then(() => {
      // Run any additional functionality if you need to. 
    });
    

    I also posted this on Angular's Github page: https://github.com/angular/angular/issues/13158#issuecomment-432275834

    0 讨论(0)
提交回复
热议问题