Showing error after form submit in angular reactive form

后端 未结 1 859
难免孤独
难免孤独 2021-01-28 10:13

I have created a reactive form and using angular-material form control.

On form submit I am calling API and that API is returning error because one of the formControl va

相关标签:
1条回答
  • 2021-01-28 11:00

    It's not exact, but I think taht using an async validator (see the docs) you can resolve your problem. The problem with asyncValidatros are is the perfomance. If you not use updateOn 'blur' or 'submit' Angular makes a call each time you change the form.

    Imagine you has a service that return an observable of true or false like

    @Injectable({ providedIn: 'root' })
    export class ApiService {
      getWebName(webName: string): Observable<boolean> {
        const isTaken = webName=="Vivek Kumar";
        return of(isTaken).pipe(delay(1000));
      }
    }
    

    You need create the formGroup using the constructor of FormGroup and FormControl to indicate when you make the valitation. It's not possible using FormBuilder

    this.testForm = new FormGroup(
      {
        name: new FormControl("Vivek Kumar", {
          asyncValidators: this.checkIfNotRegister(),
          validators: Validators.required, 
          updateOn: 'blur'
        }),
        age: new FormControl(30, {
           validators:Validators.required,
           updateOn: 'blur'
        })
      }
    );
    

    Our function "checkIfNotRegister" is

    checkIfNotRegister(): AsyncValidatorFn {
        return (control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> => {
          return this.service.getWebName(control.value).pipe(
            map(res => res ? { repeat: "name yet register" } : null)
          )
        };
      }
    

    And the .html is like

    <form [formGroup]="testForm">
        <mat-form-field class="name" appearance="outline">
            <input matInput placeholder="Name" formControlName="name">
        <mat-error *ngIf="testForm.get('name').hasError('required')">
          Name is required*
        </mat-error>
        <mat-error *ngIf="testForm.get('name').hasError('repeat')">
          Unknown server Error
        </mat-error>
        <mat-hint *ngIf="testForm.get('name').pending">Validating...</mat-hint>
      </mat-form-field>
    
      <mat-form-field class="age" appearance="outline">
            <input matInput placeholder="Age" formControlName="age">
        <mat-error *ngIf="testForm.get('age').hasError('required')">
          Age is required*
        </mat-error>
      </mat-form-field>
    
      <div>
        <button type="submit" (click)="submitForm()">Submit</button>
      </div>
    </form>
    

    See how we use <mat-hint> to show when is checking the observable

    Update only check the async validators in submit()

    If we make in submit some like:

      submitForm() {
        if (this.testForm.valid)
        {
          //Add an async validators
          this.testForm.get('name').setAsyncValidators(this.checkIfNotRegister());
          //force Angular to updateValueAndValidity
          this.testForm.get('name').updateValueAndValidity();
          //remove the async validator
          this.testForm.get('name').setAsyncValidators(null);
        }
      }
    

    Update 2019-06-27

    But this don't wait to check if is valid, so need make another step that it's susbcribe to this.testForm.statusChanges, so our submitForm becomes like

    submitForm() {
        if (this.testForm.valid) {
          this.testForm.statusChanges.pipe(take(2),last()).subscribe(res=>{
              //if res=='VALID' make something
              //if res=='INVALID'we don't need make nothing
              console.log(res)
          })
          this.testForm.get('name').setAsyncValidators(this.checkIfNotRegister());
          this.testForm.get('name').updateValueAndValidity({onlySelf:false,emitEvent:true});
          this.testForm.get('name').setAsyncValidators(null);
        }
    

    Our form not need validator onBlur or onSubmit

    this.testForm = new FormGroup(
          {
            name: new FormControl("Vivek Kumar", Validators.required),
            age: new FormControl(30, Validators.required)
          }
        );
    

    You can see in the stackblitz the final result

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