Handling Validation

In this lesson, we'll learn how to handle validation if the user inputs an invalid value.

We’re able to validate the input successfully. However, the way we’re telling the user isn’t the most magnificent way. We’ll want to provide friendlier feedback to the user. When it comes to handling feedback, Angular expects us to handle outputting the message. It will not generate a message for us.

It’s going to require some extra work, but Angular provides us with all the information we’ll need to generate a message.

Retrieving the validation errors

Currently, we’re checking if the form is valid by checking the valid property on the form group. If we want to check validation on an individual controller, we’ll need to access the controller via the group’s controls property. This will be an object of the controllers registered in the group.

ccForm.controls.name.errors

Every controller can be accessed via its key name. We’re accessing an object on the controller called errors. This will be an object of the validation rules broken by the input value.

Alternatively, we can use a method, called get(), on the form group. This will have one argument, which is the name of the controller we’d like to retrieve. Here’s an example:

ccForm.get('name').errors

Either solution works. They’ll both return the same object. We’ll be using the get() function for this project.

Displaying a message

The value of the errors object on each controller will be one of two values. It will either be null or an object. If the value is null, there are no errors. The input is considered valid. If it’s an object, it will contain a list of broken validation rules.

In the app.component.html template file, we’ll add the following, below the input, for the name:

<ng-container *ngIf="ccForm.get('name').errors">
  <div *ngIf="ccForm.get('name').errors.required" class="invalid-feedback">
    Please fill in the field.
  </div>
</ng-container>

Three things are going on here. First, we’re using the <ng-container> placeholder to contain the list of errors. We’ll be adding multiple errors in a moment. To prevent from adding unnecessary elements, we’ll be using this placeholder to group the errors.

Second, we have the ngIf directive applied to the <ng-container> placeholder. We’re checking if there are any errors. If the errors object returns null, we’ll know that there aren’t any errors. If there are, we’ll proceed to render the message.

Lastly, we’re loading the message. Before we do, we need to check what validation rules are broken. We’re using another ngIf directive to check if the required rule was broken. We can check if a rule is broken by checking if the validation rule is present on the errors object. It’s important to note that Angular will only add the validation rules broken on the input. If it is on the object, we’ll output a message.

The <div> element surrounding the element has the invalid-feedback class. This is a Bootstrap class that will output red text below the input.

Handling the minimum length validation

We have two validation rules on the input for the name. We’ve handled the first rule, which was the required rule. This will require the input to have a value.

The other validation rule we had was the minLength validation. This will require the value to have a minimum length of characters. In the template, we’ll update the error message we added to the following:

<ng-container *ngIf="ccForm.get('name').errors">
  <div *ngIf="ccForm.get('name').errors.required" class="invalid-feedback">
    Please fill in the field.
  </div>
  <div *ngIf="ccForm.get('name').errors.minlength" class="invalid-feedback">
    The value you inputted is {{ ccForm.get('name').errors.minlength.actualLength }}
    characters long.
    It must be at least {{ ccForm.get('name').errors.minlength.requiredLength }}
    characters long.
  </div>
</ng-container>

Things are a bit different this time around. Like last time, we’re checking if the minlength object is present in the errors object. This is to ensure the validation rule was broken. It’s important to note that the name of the validation in the class is minLength, but the name in the template is minlength. The letter “l” is lowercase in the template. It’s bizarre, but that’s how Angular names their validation properties.

The minlength object will contain two properties: actualLength and requiredLength. They’ll represent the current length of the value and the required length to pass the validation, respectively.

We’re using both to output a message letting the user know specifically about what they need to do to satisfy the validation.

Changing the <input> styles

We’ll make one last change. The error message will not appear because Bootstrap requires that we apply the is-invalid class to the <input> element adjacent to the error message. We’ll use the ngClass directive to dynamically apply this class.

<input type="text" class="form-control" formControlName="name"
  [ngClass]="{ 'is-invalid': ccForm.get('name').errors }">

Here’s the updated code:

Get hands-on with 1200+ tech skills courses.