Introduction to Angular Forms
Published: 2022-06-06 14:33:13


Forms are necessary for any Angular application. They are used to collect users' input data from the view of the application. This article introduces you to the power of Angular forms. We will dive into different forms and do a simple implementation of a Reactive form.

**Basics of Angular Forms**

There are two different forms for a user to input data: **Reactive** and **Template-driven** forms.

According to the [Angular Documentation](https://angular.io/guide/forms-overview):

<aside>
💡 Reactive forms: Provide direct, explicit access to the underlying forms object model. Compared to template-driven forms, they are more robust: they're more scalable, reusable, and testable.

</aside>

<aside>
💡 Template-driven: Rely on directives in the template to create and manipulate the underlying object model.

</aside>

Template-driven forms use the *ng-Model* directive, which helps bind your form to a value, hence its synchronous nature. Reactive forms follow the separation of concerns principle, where the core functionality is in the component, and the presentation layer is stored in the template. Reactive forms are also asynchronous: meaning an event occurs in a form and is then delivered instantly using a callback.

**Let’s Create our first reactive form!**

### Step 1: Import necessary modules

We will create a simple login reactive form that will have a few validation rules before the user is able to submit a form.

First, you need to add the ReactiveFormsModule from the Angular forms module in the module.ts file, for example, *app.module.ts*

<aside>
💡 The FormsModule gives the ability to work with template-driven and reactive forms

</aside>

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3vyndeiy7yxcapcgh344.png)


### Step 2:  Create the Reactive Form


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tibcw6lvs4jzm7j5w1kn.png)

The ‘loginForm’ is initialized with the type *FormGroup*. FormGroup is one of the building blocks of Angular forms. It is a collection of form controls that tracks the value and validity state of a group of Form control instances. 

We have two form fields in our login form:

- Email field - the field is **required** and **its value to be of a **minimum character length of 64
- Password field -  the field is **required** and **its value to be of a **minimum character length of 64

<aside>
💡 A validator is a function that processes a [FormControl](https://angular.io/api/forms/FormControl) or collection of controls and returns an error map or null. A null map means that validation has passed.

</aside>

### Step 3: Show the Field and Validate User Input

The presentation layer will look like this:

```jsx
<form [formGroup]='loginForm'>
    <div class="form-group">
        <label for="username">Email</label>
        <input formControlName='email' id="email" type="text" class="form-control">
    </div>
    <div class="form-group">
        <label for="password">Password</label>
        <input formControlName='password' id="password" type="text" class="form-control">
    </div>
    <button class="btn btn-primary" type="submit">Sign Up</button>
</form>
```

The formGroup directive on the form tag passes the form group instantiated on the component class while the formControlName directive passes a string with the name of your controls used in the component class.

We can go a step further to show validation error messages to indicate to a user if a field is required, or if the user has not met the validation rules set for a minimum character length or exceeded a maximum character length.

```html
<form [formGroup]="loginForm">
    <div class="form-group">
        <label for="email">Email</label>
        <input formControlName='email' id="email" type="text" class="form-control">
        <ng-container *ngIf="loginForm.get('email').invalid && loginForm.get('email').errors &&  (loginForm.get('email').dirty || loginForm.get('email').touched)">
            <small class="text-danger" *ngIf="loginForm.get('email').hasError('required')">
                This field is required.
            </small>
            <small class="text-danger" *ngIf="loginForm.get('email').hasError('maxlength')">
                The maximum length for this field is {{loginForm.get('email').errors.maxlength.requiredLength}} characters.
            </small>
        </ng-container>
    </div>
</form>
```

Instead of duplicating the code for each field and for all forms, a better approach might be to abstract this into a separate component that can be reused across the codebase.

### Step 4: Disable the submit button

Finally, we can disable the submit button if the form is invalid:

```html
<button class="btn btn-primary"  [disabled]="loginForm.invalid" type="submit">Sign Up</button>
```

Happy Learning!