简体   繁体   中英

Angular: Custom Form Validator Not Showing Mat Error

All I want to do is have the user type in a company name into an input box and it call a simple backend api to check if the company exists as they're typing it.

My API call works fine and returns "true" or "false" successfully as the user types in a value. It's just not displaying an error on the screen when it's false/company doesn't exist.

The part with "************" is where it's failing to return anything. No compile errors or runtime errors, just doesn't display a mat error when the company doesn't exist.

If you think this is an intimidating problem given the number of lines of code I don't blame you, I've been trying to figure out something seemingly simple that has taken nearly 6 hours.

my reports-view.component.ts file:

export class MyErrorStateMatcher implements ErrorStateMatcher {
    isErrorState(
      control: FormControl | null,
      form: FormGroupDirective | NgForm | null
    ): boolean {
        //console.log("blah");
      const invalidCtrl = !!(control && control.invalid);
      const invalidParent = !!(
        control &&
        control.parent &&
        control.parent.invalid
      );
  
      return invalidCtrl || invalidParent;
    }
  }

@Component({
    selector: 'app-reports-view',
    templateUrl: './reports-view.component.html',
    styleUrls: ['./reports-view.component.scss']
})
export class ReportsViewComponent implements OnInit {
    matcher = new MyErrorStateMatcher();

    CompanyNameInputForm: FormGroup;

    companyNameValidator() {
        return (form: FormGroup) => {
            this.reportsPageService.doesCompanyNameExist(form.controls.companyName.value).subscribe((data) => {
                console.log(data);
                if (form.controls.companyName.value === "") {
                    console.log("returning null inside if");
                    return null;
                }
                else if (data==false) {
                    console.log("company name does not exist");

                    ******************return { invalidCompanyName: true };******************

                }
                console.log("returning null at end");
                return null;
            });
        }
        
    }
    ngOnInit() {

        this.CompanyNameInputForm = this.formBuilder.group(
            {
                companyName: [""]
            },
            { validator: this.companyNameValidator() }
        );
    
        this.CompanyNameInputForm.setValue({
            companyName: this.companyName
        });
    }
   constructor(private routingService: RoutingService, public reportsPageService: ReportsPageService, 
    private formBuilder: FormBuilder) {
        this.BASE_URL = routingService.getBaseUrl();
    }
}

in my service file:

doesCompanyNameExist(companyName: string):any {
        return this.http.post(`${this.BASE_URL}/RESTAPI/reports/doesCompanyNameExist?companyName=${companyName}`,
        this.httpOptions);
}

the html:

<form [formGroup]="CompanyNameInputForm">
      <mat-form-field>
            <input matInput placeholder="Company name" type="text" formControlName="companyName" [errorStateMatcher]="matcher">
             <mat-error *ngIf="CompanyNameInputForm.hasError('invalidCompanyName')">Company does not exist
             </mat-error>
      </mat-form-field>
</form>

You are trying to validate the form group synchronously , while the validation results come after asynchronous check in your service.

You need to create an AsyncValidator and to update the configuration of the FormGroup .

This means you have to build the group like this:

 this.CompanyNameInputForm = this.formBuilder.group(
  {
   companyName: [""],
  },
  { asyncValidator: this.companyNameValidator }
 );

Then you will need to update the validator method:

  companyNameValidator(form: FormGroup): Observable<ValidationErrors | null> {
    return this.reportsPageService.doesCompanyNameExist(form.controls.companyName.value)
      .pipe(map((data) => {
        console.log(data);
        if (form.controls.companyName.value === "") {
          console.log("returning null inside if");
          return null;
        }
        else if (data == false) {
          console.log("company name does not exist");
          return { invalidCompanyName: true };
        }
        console.log("returning null at end");
        return null;
      }));
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM