Using Angular 12 I have a simple example form with Client and Server Validation.
I want to show Client Validation errors only after first Form submission;
I will show Server Validation errors after Client Validation is succeeded.
Server Validation errors are added as 'incorrect' field in Form Field errors.
I am using Reactive Forms.
The form is working as expected but I'm not sure if my implementation is the best option.
Component's HTML
<form [formGroup]="form">
<label for="email">Email</label>
<input id="email" type="text" formControlName="email">
<span class="error" *ngIf="form.get('email')?.invalid && form.get('email')?.touched">
{{form.get('email')?.errors?.incorrect}}
<ng-container *ngIf="form.get('email')?.errors?.required">Email required</ng-container>
<ng-container *ngIf="form.get('email')?.errors?.email">Invalid email</ng-container>
</span>
<button type="submit" (click)="send()" [disabled]="submitted">Send</button>
</form>
Component's Typescript
export class Component implements OnInit {
form: FormGroup;
submitted: boolean;
constructor(private service: Service) {
this.form = this.formBuilder.group({
email: ['', [Validators.required, Validators.email]],
});
this.submitted = false;
}
send() {
this.submitted = true;
this.form.markAllAsTouched();
if (this.form.valid) {
this.service.send({email: this.form.value.email}).subscribe(
(next: Payload<Response>) => {
console.log("SUCCESS");
},
(error) => {
if (error.status === 400)
new FormGroupErrorBuilder(this.form).setErrors(error.errors);
this.submitted = false;
}
);
} else {
this.submitted = false;
}
}
}
FormGroupErrorBuilder
This is how I am adding server errors to Angular's FormGroup:
export class FormGroupErrorBuilder {
formGroup: FormGroup;
constructor(formGroup: FormGroup) {
this.formGroup = formGroup;
}
setErrors(errors: Error[]) {
for (let error of errors) {
var control = this.formGroup.get(error.name);
if (control)
control.setErrors({ incorrect: error.message });
}
}
}
Questions
Is it acceptable to use
this.form.markAllAsTouched();to fire validation for all form fields on first submit?Using the condition
*ngIf="form.get('email')?.invalid && form.get('email')?.touched"a good option to show the form field errors?
Any suggestion to improve the code is welcome ...
Note:
I am using submitted variable to control if the submit button is disabled or not and to change its CSS styles.
Take a look to Async custom validators in the docs:
If you create your formGroup with the option {updateOption:'submit'} I think you can achieve in other way
some like: e.g. (I put the validator in the FormGroup, you can put it in the own control Email) -then you should change the "validateEmail" function.
NOTE: I don't see clear in your code, when you subscribe to the service. You "catch" the error, Generally an API return some like
{success:true}or{error:'the email is yet!'}, but don't return a status 400 if ther'e not an error in the call -your API can response some like above but you received the response in success, not in error.