Angular Forms and Validations
Angular Forms and Validations
https://angular-templates.io/tutorials/about/angular-forms-and-validations 1/22
28/1/2019 Angular 5 Forms and Validations | Angular Templates
Forms (/tutorials/tag/forms)
We will go through the best practices to design user-friendly forms and validations using angular. After
that we will go through the differences between each Angular forms; template driven forms and reactive
forms.
For this angular 5 tutorial we built an example project with different forms and validations to help you
understand everything about data collection using angular reactive forms. Also we will explore some
techniques to improve the user experience of your angular forms.
We want this to be an excellent angular forms tutorial, so we created advanced custom validators to show
you how to validate passwords, phone numbers and unique usernames. Of course we will rst explain
about some basic angular form validation examples such as: how to use an email validation pattern to
validate your email inputs.
If this is your rst time using angular reactive forms, this tutorial will help you understand the core
concepts and fundamentals of angular FormControl, angular FormGroup, angular FormBuilder, the
different types of built-in validators and how to create your custom validators.
Building easy-to-use forms requires design and user experience skills, as well as a framework with support
for two-way data binding, change tracking, validation, and error handling such as Angular :)
If you need to go deeper about angular main building blocks as well as the best practices for building a
complete app with Angular you can check this Angular Tutorial: Learn Angular from scratch step by step
(/tutorials/about/learn-angular-from-scratch-step-by-step)
Let’s keep in mind that the real objective of forms is gathering data. As it always happens in software, there
are many different ways of sending and handling data in your server. This depends a lot on the backend and
the nature of your business logic, so we are not going to cover this topic in this tutorial. However, if you
https://angular-templates.io/tutorials/about/angular-forms-and-validations 2/22
28/1/2019 Angular 5 Forms and Validations | Angular Templates
want to use the MEAN stack (Mongo, Express, Angular and Node), you should read Building an Angular
example app step by step. (/tutorials/about/learn-angular-from-scratch-step-by-step)
Remember you can download all the source code using the GET THE CODE button from above.
There is an important difference between them and that is: Reactive forms are synchronous while
Template-driven forms are asynchronous.
Before we continue with our example app using angular reactive forms, let’s de ne the difference between
reactive and template-driven forms from a high level perspective.
When coding reactive forms, we will avoid directives like required, ngModel, NgForm and such. The idea
is that we actually use the underlying APIs to do it for us. In a sense, instead binding Object models to
directives like it happens in template-driven forms, we create our own instances inside a component class
and build our very own JavaScript models. This approach has a lot more power and is extremely productive
to work with since it allows us to write expressive code (a very testable one that keeps all the logic in the
same place) instead of dividing it over different form templates.
With reactive forms, you will be able to create and manipulate form control objects directly in the
Component. Since the component class has access to the form control structure and the data model, you
can push data model values into the form controls as well as pull values that have been changed by the
user. The component is able to observe changes in the form control state and react to them. This is
specially useful for showing a validation message.
One of the advantages that working directly with form control objects brings you is that value and validity
updates are always synchronous and under your control. You won’t nd the timing issues that sometimes
affect a template-driven form. Also, reactive forms tend to be easier to unit test.
https://angular-templates.io/tutorials/about/angular-forms-and-validations 3/22
28/1/2019 Angular 5 Forms and Validations | Angular Templates
You can place HTML form controls (such as <input> or <select> ) in the component template and bind
them to data model properties, using directives like ngModel .
With template-driven forms, you don’t create Angular form control objects. They are created by Angular
directives using information from your data bindings. You don’t have to push and pull data values around
because Angular handles that for you through the ngModel directive. Angular updates the mutable data
model according to user changes as they occur.
A few examples of these directives are; ngModel, required, maxlength . In template-driven forms we
specify directives to bind our models, values, validations and more, so we are actually letting the template
do all the work on the background.
Although this approach means less code in the component class, the template driven forms are
asynchronous which may complicate the development in more advanced scenarios.
Template driven forms may resemble more as how forms used to be in AngularJS (v 1.0), probably, that’s
why people still use them as a familiar option.
Neither one. They are two different architectural paradigms with their own advantages and
disadvantages. You can choose the approach that suits you the best. This way you are free to even decide
using both in the same application.
FormControl : it tracks the value and validity status of an angular form control. It matches to a HTML form
control like an input.
The following is an example which shows a FormControl for the ‘name’ property which should not be
empty.
https://angular-templates.io/tutorials/about/angular-forms-and-validations 4/22
28/1/2019 Angular 5 Forms and Validations | Angular Templates
FormGroup : it tracks the value and validity state of a FormBuilder instance group. It aggregates the values
of each child FormControl into one object, using the name of each form control as the key. It calculates its
status by reducing the statuses of its children. If one of the controls inside a group is invalid, the entire
group becomes invalid.
FormArray : is a variation of FormGroup . The main difference is that its data gets serialized as an array, as
opposed to being serialized as an object in case of FormGroup. This might be especially useful when you
don’t know how many controls will be present within the group, like in dynamic forms.
FormBuilder : is a helper class that creates FormGroup , FormControl and FormArray instances for us. It
basically reduces the repetition and clutter by handling details of form control creation for you.
this.validations_form = this.formBuilder.group({
username: new FormControl('', Validators.required),
email: new FormControl('', Validators.compose([
Validators.required,
Validators.pattern('^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$')
]))
});
Angular is packed with its own validators. In a moment we are going to check out how to use some of the
Angular form validators to make our app signi cantly better for our users.
Forms are also a bottleneck of the conversion funnel, because they require the user to perform a task
much more complex than just a click, by thinking and typing all the required information by the form. This
may be frustrating when you type all the information and, in the end, you need to retype all over again,
which is why you have to strive to do your best to have an awesome user experience to reduce users
frustrations and conclusively improve your funnel conversion.
Some people say that user experience is often more important than what the app offers itself. So before we
start coding, it’s important to take some time to analyze which elds are really needed. When designing
the mock up, always try to include the elds that are essential to you, knowing that the bigger the form, the
bigger chance you have of losing some users.
Keep in mind that simplicity is well appreciated, ask only for what you
precisely need.
From a design perspective, Angular Material has a wide collection of nice form elements and form inputs
for you to choose. From the UX point of view we will make use of angular form validations to enhance the
experience of our angular website app.
Best practices say you should always validate all user inputted data via backend and we agree with that
statement. However, by also validating via frontend, you can improve the user experience and perceived
response time.
Real time validation: It means validating as you type. These are super handy and are the default for
Angular Validators.
On blur validation: It may be less annoying for certain cases as we only validate when the user focus out
from the form input. However, the user will only see the errors once he moves to the next input. As we can
see in the of cial documentation (https://angular.io/api/forms/AbstractControl#updateOn) Angular 5 has
a new option for your ngModel updateOn: 'blur' and you can use it like this:
https://angular-templates.io/tutorials/about/angular-forms-and-validations 6/22
28/1/2019 Angular 5 Forms and Validations | Angular Templates
In our forms and validation example project we are using the following Material components: form elds,
inputs, date picker, checkbox, select and buttons.
For this angular forms and validations example we created two separate forms: user details and account
details.
Bio Text area 1. can’t be more than 256 characters long 1. Maxlength 256
https://angular-templates.io/tutorials/about/angular-forms-and-validations 7/22
28/1/2019 Angular 5 Forms and Validations | Angular Templates
In Angular Admin Template we have lots of different inputs and validations that you can use in your
angular project. There are basic and also advanced forms and validations that you should de nitely
check in Angular Admin Template (/product/angular-admin-template).
https://angular-templates.io/tutorials/about/angular-forms-and-validations 8/22
28/1/2019 Angular 5 Forms and Validations | Angular Templates
https://angular-templates.io/tutorials/about/angular-forms-and-validations 9/22
28/1/2019 Angular 5 Forms and Validations | Angular Templates
In reactive forms, instead of adding validators through attributes in the template (like it happens with
template driven forms), you add validator functions directly to the form control model in the angular
component class. Angular will call these functions whenever the value of the control changes.
You can choose between writing your own validator functions and using some of the Angular built-in
validators.
Built-in validators are stock validators provided by Angular. For a full list of Angular built-in validators,
here (https://angular.io/api/forms/Validators) you can see the Validators API reference. However, built-in
validators won't always match the exact use case of your application, so sometimes you will want to create
a custom validator for your angular website.
pattern : Validator that requires a control to match a regex to its value. You can nd more information
about regex patterns in the PatternValidator reference.
compose : is used when more than one validation is needed for the same form eld.
required : Validator that requires controls to have a non-empty value. It also validates that the value
matches the input type. For example, if the input is of “email” type, then the input will be valid if it’s not
empty and if the value is of email type.
Let’s start with some name and email inputs validations. These are the requirements for our form controls:
We will de ne our User Details Form with a FormGroup. To create the FormGroup we will use an instance
of the FormBuilder. Check the following typescript code to see how you can achieve this. Note that for the
full name and bio we preloaded some default data. You can nd this code in src/app/form-
component/form.component.ts
https://angular-templates.io/tutorials/about/angular-forms-and-validations 10/22
28/1/2019 Angular 5 Forms and Validations | Angular Templates
Now we have to create the form, inputs and their error messages inside our template le. Below is the html
code for de ning the form and the name input. Download the source code (click the GET THE CODE
button from the beginning of this page) of this angular 5 forms and validations example to see all the
inputs. We didn’t put it here because we don’t want to make this tutorial super large.
All the mat tags are components from angular material like mat-error which is the way to display the error
messages in our mat-form-field .
<mat-form-field> is a component used to wrap several Angular Material components and apply common
styles such as underline, oating label, and hint messages. Read more in the of cial documentation
(https://material.angular.io/components/form- eld/overview).
So we have to create our FormGroup like we explained above and create a FormControl to de ne our
email form control with its validations.
https://angular-templates.io/tutorials/about/angular-forms-and-validations 11/22
28/1/2019 Angular 5 Forms and Validations | Angular Templates
this.accountDetailsForm = this.fb.group({
email: new FormControl('', Validators.compose([
Validators.required,
Validators.pattern('^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$')
])),
// more form inputs
})
Then, in the template le, the html looks just like the other inputs code with a mat-form-field enclosing
the input and the mat-error .
<mat-form-field class="full-width">
<input matInput type="email" placeholder="Email" formControlName="email" required>
<mat-error *ngFor="let validation of account_validation_messages.email">
<mat-error class="error-message" *ngIf="accountDetailsForm.get('email').hasError(validation.type)
</mat-error>
</mat-form-field>
I forgot to mention that we have de ned our error messages also in our src/app/form-
component/form.component.ts le. Each input can have more than one validation that’s why we created
an array of validation messages for each form input.
For example for our Account Details form we have the following error messages:
account_validation_messages = {
'username': [
{ type: 'required', message: 'Username is required' },
{ type: 'minlength', message: 'Username must be at least 5 characters long' },
{ type: 'maxlength', message: 'Username cannot be more than 25 characters long' },
{ type: 'pattern', message: 'Your username must contain only numbers and letters' },
{ type: 'validUsername', message: 'Your username has already been taken' }
],
'email': [
{ type: 'required', message: 'Email is required' },
{ type: 'pattern', message: 'Enter a valid email' }
],
'confirm_password': [
{ type: 'required', message: 'Confirm password is required' },
{ type: 'areEqual', message: 'Password mismatch' }
],
'password': [
{ type: 'required', message: 'Password is required' },
{ type: 'minlength', message: 'Password must be at least 5 characters long' },
{ type: 'pattern', message: 'Your password must contain at least one uppercase, one lowercase, and
],
'terms': [
{ type: 'pattern', message: 'You must accept terms and conditions' }
]
}
https://angular-templates.io/tutorials/about/angular-forms-and-validations 12/22
28/1/2019 Angular 5 Forms and Validations | Angular Templates
Then in our mat-error we iterate through the error messages of each speci c input. Let’s go back to the
email validation example. We iterate the account_validation_messages.email messages and for each of
them we show it only if the form control has an error of that type and the control is dirty or touched. What
does that mean? It means that the user has already touched the input.
Validate that the username is unique (checks against a fake server if the username is already taken).
Validate that the con rm password input value is equal to the password input value.
Validate if the phone is valid for the selected country.
Note that in a real application you will have to check this validator against your username database.
With fc.value we obtain the value in the username eld, so we can control the usernames we won't allow
to enter.
Then, in the typescript le where we have de ned our form, we should import our custom validator.
https://angular-templates.io/tutorials/about/angular-forms-and-validations 13/22
28/1/2019 Angular 5 Forms and Validations | Angular Templates
this.validations_form = this.formBuilder.group({
username: new FormControl('', Validators.compose([
UsernameValidator.validUsername,
Validators.maxLength(25),
Validators.minLength(5),
Validators.pattern('^(?=.*[a-zA-Z])(?=.*[0-9])[a-zA-Z0-9]+$'),
Validators.required
])),
})
We used minLength(5) and maxLength(25) to ensure the minimum and maximum length of the value.
We also used required to avoid this input to be left empty, and ng-pattern="^(?=.*[a-zA-Z])(?=.*[0-
9])[a-zA-Z0-9]+$" to force a correct input value containing letters and numbers.
https://angular-templates.io/tutorials/about/angular-forms-and-validations 14/22
28/1/2019 Angular 5 Forms and Validations | Angular Templates
if (!subscribe) {
subscribe = true;
countryControl.valueChanges.subscribe(() => {
phoneControl.updateValueAndValidity();
});
}
if (isValidNumber) {
return undefined;
}
} catch (e) {
console.log(e);
return {
validCountryPhone: true
};
}
return {
validCountryPhone: true
};
} else {
return undefined;
}
};
}
}
The phone directive controls that the value from the phone number input is correct for the selected
country.
Then, in the typescript le where we have de ned our form (form.ts), we should import our custom
validator. In form.ts we have a FormGroup with the phone input and the country selector so when the
value changes in one of these elds the directive checks if both are correct.
https://angular-templates.io/tutorials/about/angular-forms-and-validations 15/22
28/1/2019 Angular 5 Forms and Validations | Angular Templates
Required
Min length (5)
Must contain letters (both uppercase and lowercase) and numbers
User must re-type password to ensure correctness
We added the following code in a new password.validator.ts le to create our PasswordValidator which
validates that the password was re-typed correctly. It’s like a password match validator.
if (valid) {
return null;
}
return {
areEqual: true
};
}
}
https://angular-templates.io/tutorials/about/angular-forms-and-validations 16/22
28/1/2019 Angular 5 Forms and Validations | Angular Templates
Then, in the typescript le where we have de ned our form (form.ts), we should import our custom
password validator and add the other simple validations: password no shorter than 5 chars, and with
letters and numbers.
And then in for the html of this password inputs we do the following:
<div formGroupName="matching_passwords">
<mat-form-field class="full-width">
<input matInput type="password" placeholder="Password" formControlName="password" required>
<mat-error *ngFor="let validation of account_validation_messages.password">
<mat-error class="error-message" *ngIf="accountDetailsForm.get('matching_passwords').get('passw
</mat-error>
</mat-form-field>
<mat-form-field class="full-width">
<input matInput type="password" placeholder="Confirm Password" formControlName="confirm_password"
<mat-error *ngFor="let validation of account_validation_messages.confirm_password">
<mat-error class="error-message" *ngIf="(accountDetailsForm.get('matching_passwords').get('conf
</mat-error>
</mat-form-field>
</div>
Noticed the error state matcher in the con rm password input? We created a ParentErrorStateMatcher
which implements from ErrorStateMatcher and its goal is the validate that the form group is valid. In this
case the form group includes all the password input validations and the con rm password input
validations.
https://angular-templates.io/tutorials/about/angular-forms-and-validations 17/22