How to do and show server validation errors in angular form
Asked Answered
D

3

6

I'm new to angular. I was trying something and got stuck. In my form, I want to show server validation response as error coming from a laravel rest api. But don't know how to store and show it in the template. I am able to log it to the console but not able to move further with the error message.

The response is somewhat like this-

{
    "message": {
        "firstname":["The firstname field is required."],
        "lastname":["The lastname field is required."],
        "email":["The email field is required."],
        "password":["The password field is required."]
    }
}

The Service code:

registerUser(user): Observable<any> {
    return this.http
      .post<any>(`${this.url}/register`, user)
      .pipe(map(res => res.message));
}

The register user method in component class:

registerUser() {
    console.log(this.registrationForm.value);
    this.authService.registerUser(this.registrationForm.value).subscribe(
        res => console.log(res),
        err => console.log(err)
    );
}

Also, correct me if I'm going wrong anywhere and how should I correct it

Dropper answered 1/9, 2019 at 15:41 Comment(7)
Welcome to Stackoverflow, I would like to add an important point, as you are developing with Angular, you need to handle validation at front-end side first (i.e. in Angular first) and that should make sure that you don't need to show server-side validation messageFuturism
You might wanna look at jasonwatmore.com/post/2019/06/15/… and if you are using reactive forms then you can look at jasonwatmore.com/post/2019/06/14/…Futurism
I have already done the client-side validation. But still, want to see if there's a way to show server-side validation messages.Dropper
Tell me this, if you have placed client side validation, means you are making sure your model is valid for server, then how it is possible that your server will ever throw you validation message if you calling the API from your code which again has made sure that model is valid?Futurism
I mean I have done client-side validations in other projects. But this time, I am trying to do the same with server side validation.Dropper
@MohammedDawoodAnsari the server can throw a validation error if you are registering a user that was taken after you submit your form, another validation error is an incorrect password while logging in.Bruni
Well this is the correct example, because this is something you can only check on server, whereas OP question is related to mandatory validations, no offence but in my view checking for a mandatory field and a password verification are completely different thingsFuturism
B
7

My understanding is that you'll like to display the error messages on each field that failed a validation, i have done that some times.

The shared approach handles the following:

  • After getting an error from the server, the form stays as invalid until the user updates the related fields.
  • In case of general errors (not related to any form field), they are rendered outside of the form by a service which knows how to present them.

The general idea is to create a reusable service that knows how to detect errors and how to add them to the reactive forms, this service can handle client and server errors, let's call it ErrorService, this service can have a function like renderServerErrors(form: FormGroup, response: ErrorResponse) which gets invoked on each server response and verify whether there is any error to render in the form.

An error is rendered into the form is the form has the given field.

You can see the following files to guide you:

If you pay attention, the error responses are handled with this.errorService.renderServerErrors(this.form, response) which does everything, see it live at https://cryptocoinalerts.net/login.

Some more details

  • The server return validation errors only when the response status is non 2xx, like 400 (Bad Request), 500 (Server Error), etc. This implies that your error handler callback will get invoked (err => console.log(err)), if this assumption is not true, you'll need another check to verify if there is any error on the response.
  • There are two types of errors, the ones tied to a field, and the ones that aren't, the latter ones need a separate way to display them.
  • The example shows your how it works for a slightly different server response, which is:
{
  "errors": [
    {
      "type": "field-validation-error",
      "field": "password",
      "message": "Incorrect password"
    }
  ]
}
  • When a field is invalid, it gets a red border with the validation error displayed.
  • When a field has valid data, it gets a green border.

This is how it looks: enter image description here

Feel free to ask if anything is not clear.

Bruni answered 1/9, 2019 at 16:45 Comment(0)
D
2

So this is how it worked.
Thanks to all for answering my question.
The component class method:

errors = [];
  registerUser() {
    console.log(this.registrationForm.value);
    this.authService.registerUser(this.registrationForm.value).subscribe(
      res => console.log(res),
      err => {
        this.errors = err.error.message;
        console.log(this.errors);
      }
    );
  }

The form in the template:

 <div class="form-group">
            <label>Firstname</label>
            <input
              type="text"
              formControlName="firstname"
              name="firstname"
              class="form-control rounded-0"
              [class.is-invalid]="errors.firstname"
            />
            <span *ngIf="errors.firstname" class="text-danger">{{
              errors.firstname
            }}</span>
          </div>
Dropper answered 27/11, 2020 at 19:5 Comment(0)
S
1

Component.html:

<input formControlName="firstName">
<span *ngIf="errMsg.firstname"> {{errMsg.firstname}} </span>
<input formControlName="lastname">
<span *ngIf="errMsg.lastname"> {{errMsg.lastname}} </span>
<input formControlName="email">
<span *ngIf="errMsg.email"> {{errMsg.email)}} </span>
<input formControlName="password">
<span *ngIf="errMsg.password"> {{errMsg.password)}} </span>
<button type="submit" (click)="registerUser()>Submit</button>

Component.ts:

errMsg = [];
registerUser() {
   console.log(this.registrationForm.value);
   this.authService.registerUser(this.registrationForm.value).subscribe(
        res => console.log(res),
        err => {
          console.log(err)
          this.errMsg = err
        }
    );
}
Spectre answered 1/9, 2019 at 16:27 Comment(1)
Your html uses the errMsg variable while the errorMessage is the defined one, also, the name is misleading because it doesn't represent a single error but several ones, I would call it fieldErrors instead. And, you are painting the array instead of the actual error messages. Last, this will give issues while detecting whether the form has validation errors, by default, it won't have which can allow you to submit the same info again.Bruni

© 2022 - 2024 — McMap. All rights reserved.