Reputation: 5050
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 value is invalid
For example Website already registered
.
Now, I want to show this error msg in , But the error is not showing.
<mat-form-field class="full-width website"
[appearance]="matAppearance">
<mat-label>Website URL</mat-label>
<input matInput
placeholder="Website URL"
name="website"
formControlName="website">
<mat-error *ngIf="configurationForm.get('website').hasError('required')">
<strong>(required)</strong>
</mat-error>
<mat-error *ngIf="configurationForm.get('website').hasError('pattern')">
Invalid URL
</mat-error>
<mat-error *ngIf="websiteErrMsg">{{websiteErrMsg}}</mat-error>
</mat-form-field>
public submitForm() {
this.testService.register().subscribe(
sucRes => {
console.log('done);
},
errRes => {
if (errRes.error === 'Website is already registered') {
this.websiteErrMsg = 'Website Already Registered!';
}
}
);
}
Question 1: What mistake I am doing?
Edit:
I have tried changing mat-error
or div
, then is working. Now wanted to know why it is not working with mat-error
Upvotes: 0
Views: 3236
Reputation: 58039
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
Upvotes: 1