Angular Form Validation
Tags: angular, formvalidation, typescript, validation
Published: 2023-06-15 10:21:03

**Introduction:**
Angular forms play a important role in creating dynamic and interactive web applications. Whether you're building a simple contact form or a complex multi-step wizard, Angular provides powerful features and tools to handle form validation, data binding, and user interactions. In this post, we will explore the everything we need to know about types of forms in angular and it's validations.

**Table of Contents:**

[1. Angular Forms & Types](#chapter-1)
[2. Template-Driven Forms](#chapter-2)
[3. Reactive Forms](#chapter-3)
[4. Advanced Form Handling Techniques](#chapter-6)

## 1. Angular Forms & Types <a name="chapter-1"></a>
There are mainly two types of forms we need to know in angular,
`i)  Template-driven Forms
ii) Reactive Forms`
Now let's see how to use this forms with example.

## 2. Template-Driven Forms <a name="chapter-2"></a>
This is the type of form that uses `ngModel` directive to keep track of input using `two-way binding`.

The form which uses this kind of `ngModel` mechanism is now called Template-Driven forms.

`ngModel` and other form related directives are not available by default. So, before we start we need to explicitly import them into our application.

```typescript
// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';


import { AppComponent } from './app.component';
import { TemplateDrivenFormsComponent } from './template-driven-forms/template-driven-forms.component';
import { FormsModule } from '@angular/forms'; // <-- import from angular forms


@NgModule({
  declarations: [AppComponent, TemplateDrivenFormsComponent],
  imports: [BrowserModule, FormsModule], // <-- add it here
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}

```

We've enable the `Template Driven Forms` by adding FormsModule in to our application.

### Our First Template-Driven form

```html
<!-- template-driven-forms.component.html -->
<div>
    <h1>Template-driven Form</h1>
    <form #myForm="ngForm" (ngSubmit)="onSubmit(myForm.value)">
        <div>
            <label>First Name:</label>
            <input type="text" name="firstName [(ngModel)]="user.firstName" required>
        </div>
        <div>
            <label>Last Name:</label>
            <input type="text" name="lastName" [(ngModel)]="user.lastName" required>
        </div>
        <div>
            <label>Password:</label>
            <input type="password" name="password" [(ngModel)]="user.password" required>
        </div>
        <button type="submit" [disabled]="!myForm.valid">Submit</button>
    </form>
</div>
```

``` typescript
// template-driven-forms.component.ts
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-template-driven-forms',
  templateUrl: './template-driven-forms.component.html',
  styleUrls: ['./template-driven-forms.component.scss'],
})
export class TemplateDrivenFormsComponent implements OnInit {
  user = {
    firstName: 'foo',
    lastName: 'bar',
    password: 'foo@bar',
  };

  constructor() {}

  ngOnInit(): void {}

  onSubmit(user: typeof this.user) {
    console.log(user);
  }
}

```
#### ngForms <a name="ref"></a>
You can clearly see that we've created a reference for `ngForm` template as `myForm`. `ngForm` can be only be created for HTML `<form>` element.

This template is responsible for tracking all the of the form, which contains the value of form fields.

Also `ngForm` keeps track of the validity state of the form, that depends on the validity state of each of it's form field.

#### ngSubmit
Next to `(ngSubmit)` this event prevent the submission form to call backend HTTP POST request, like in the case of a plain HTTP form submit.

`ngSubmit` directive will ensure that plain form submit not to occur instead it calls `onSubmit(myForm.value)` function with the value of the form that can be accessed by the reference(myForm) we've created

#### CSS classes
Angular FormsModule provide css classes to apply style to the input based on the state of the input field.
> ng-touched or ng-untouched
> ng-valid or ng-invalid
> ng-pristine or ng-dirty
These are the six classes provided by FormsModule for each form field in the form.

These validity states can be accessed by,

```typescript
myForm.{nameOfField}.$touched
myForm.{nameOfField}.$valid
myForm.{nameOfField}.$dirty
// validity state of the form that we used to disable the button
myForm.valid
```
## 2. Reactive Forms <a name="chapter-3"></a>
A reactive form is pretty much like template-driven form. But in order to achieve this we need to add another module called `ReactiveFormsModule`.

```typescript
// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';


import { AppComponent } from './app.component';
import { TemplateDrivenFormsComponent } from './template-driven-forms/template-driven-forms.component';
import { ReactiveFormsModule } from '@angular/forms'; // <-- import from angular forms


@NgModule({
  declarations: [AppComponent, TemplateDrivenFormsComponent],
  imports: [BrowserModule, ReactiveFormsModule], // <-- add it here
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}

```

Note that we've imported `ReactiveFormsModule` instead of `FormsModule` and that enables us to use reactive forms in our application.

### Our First Reactive form

```html
<!-- reactive-forms.component.html -->
<div>
    <h1>Reactive Form</h1>
    <form [formGroup]="form" (ngSubmit)="onSubmit()">
        <div>
            <label>First Name:</label>
            <input type="text" formControlName="firstName">
        </div>
        <div>
            <label>Last Name:</label>
            <input type="text" formControlName="firstName">
        </div>
        <div>
            <label>Password:</label>
            <input type="password" formControlName="password">
        </div>
        <button type="submit" [disabled]="!form.valid">Submit</button>
    </form>
</div>

```
Note that we haven't used any [references](#ref) of form and we've removed the `required` validation in <input> and also there is no ngModel.
And That's the magic of reactive forms each and every control of the form is in our hands (i.e) we can control every state and value of each form fields in the TS file of this component.

#### FormGroup <a name="group"></a>
`FormGroup` is the main thing we need to know about Reactive Forms and it has the control of every form fields that contains.

```typescript
// reactive-forms.component.ts
import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';

@Component({
  selector: 'app-reactive-forms',
  templateUrl: './reactive-forms.component.html',
  styleUrls: ['./reactive-forms.component.scss'],
})
export class ReactiveFormsComponent implements OnInit {
  form = new FormGroup({
    firstName: new FormControl('', Validators.required),
    lastName: new FormControl('', Validators.required),
    password: new FormControl('', Validators.required),
  });

  constructor() {}

  ngOnInit(): void {}
  onSubmit() {
    console.log('reactive form submitted');
    console.log(this.form);
  }
}

```

We can see that the form is really just a FormGroup, which keeps track of the global form value and the validity state.

Using this form group we can create simple form like this and also any kind of complex forms and even `FormArray` 

`FormGroup` contain multiple `FormControl` and that is the name we've used inside HTML `<input>` tag as `formControlName` so that we can control that input tag.

This form have all the control over it's form fields like,

```typescript
form.valid
form.invalid
form.control["firstName"].valid & .invalid
form.control["firstName"].touched & .untouched
form.control["firstName"].pristine
form.control["firstName"].enabled & .disabled
// or we can also get the fields using
form.get('firstName')
```

The same thing we've done in template-driven forms.

Also it has many features like,
1. `reset()` the form.
2. `setValue('')` to any form fields.
3. `patchValue('')` to any form fields.
4. `setValue('')` to form and it need every value of form 
    field.
5. `patchValue('')` to form and it doesn't need every value of 
    form field.
6. `setError('')` to any form fields.
7. we can track each input change using 
   `.valueChanges.subscribe((value) => {console.log(value)})`


#### FromControl
It is used to create field inside the (FormGroup)[#group].
It contains the fields default value, disabled or enabled state and validation using Validators

```
new FormControl({value:"",disabled:false}, [Validators.required])
```

#### Validators
It is used to validate the form field in many ways like,

```typescript
Validators.required
Validators.email
Validators.min
Validators.max
Validators.minLength
Validators.maxLength
Validators.pattern // we can create validation using regEx
```

These validations errors are accessed using the `FormGroup`.

```
this.form.errors // will return all the errors in the form
this.form.controls["field-name"].errors // will return errors of particular field
```

There are many advanced techniques in Reactive forms like,
1. Form Builder Api
2. Form Array
3. Error Handling
Let's see these topics in the next post.

Happy Coding 💻 :).