DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • The Most Popular Angular UI Libraries To Try in 2021
  • Recursive Angular Rendering of a Deeply Nested Travel Gallery
  • 50+ Top Angular Interview Questions and Answers
  • Create a Beautiful Login Form With Angular Material

Trending

  • How the Go Runtime Preempts Goroutines for Efficient Concurrency
  • Why High-Performance AI/ML Is Essential in Modern Cybersecurity
  • Docker Model Runner: Streamlining AI Deployment for Developers
  • A Modern Stack for Building Scalable Systems
  1. DZone
  2. Coding
  3. Frameworks
  4. How to Create Reactive Forms in Angular

How to Create Reactive Forms in Angular

In this post, we got over a how to create reactive forms in your Angular application step-by-step. Read on to get started coding!

By 
Dhananjay Kumar user avatar
Dhananjay Kumar
·
Dec. 31, 17 · Tutorial
Likes (14)
Comment
Save
Tweet
Share
24.4K Views

Join the DZone community and get the full member experience.

Join For Free

Out of the box, Angular provides us with two types of forms:

  1. Template Driven Forms
  2. Reactive Forms

In Template Driven Forms, you create controls on the component template and bind data using ngModel. With these, you do not create controls, form objects, or write code to work with pushing and pulling of data between component class and template; Angular does all of these tasks for you. In template driven forms, there is very little code for validations in the component class, and they're asynchronous.

In reactive forms, you create form controls as trees of objects in the component class and bind them to the native form controls in the template. All validations and the creation of form controls are written in the component class. In Reactive Forms, all validations and changes in the state of native forms are synchronous, so you can write code in the component class to observe them. You should choose to create reactive forms when the data model is immutable and usually mapped to a database.

The major difference between these two approaches of creating forms? In reactive forms you do not use directives such as ngModel, required, etc. You create all controls and their validations in the component class. Reactive forms are easy to test and maintain, so in this post we will learn to create a basic Reactive Form, using FormControl, FormGroup, FormBuilder class, and adding validations.

Step 1: Add Reactive Forms Module

To start working with reactive forms, first add ReactiveFormsModule in the App Module as shown in the next code block:

import {ReactiveFormsModule} from '@angular/forms';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule, ReactiveFormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Step 2: Import Required Module in Component

Next, you need to import the required reactive forms classes such as FormGroup, FormControl, and FormArray in the component class. We will use these classes to construct our reactive form. After importing these classes, the component class should look like what I've got below:

import { Component } from '@angular/core';
import { FormGroup, FormControl, FormArray } from '@angular/forms';
@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent {
    title = 'Reactive Forms Demo';
}

Your component class can be different from the AppComponent created above depending on your implementation; however, here we have imported FormGroup, FormControl, and FormArray classes. Let's learn about these classes one by one.

Step 3: Using the FormControl class

The FormControl class corresponds to one individual form control, tracking its value and validity. While creating your reactive form, you will create an object of the FormControlclass. The FormControl constructor takes three parameters:

  1. Initial data value, which can be null.
  2. An array of synchronous validators. This is an optional parameter.
  3. An array of asynchronous validators. This is an optional parameter.

In the component class, you can create a FormControl as shown in the code below:

export class AppComponent {
    email = new FormControl('');
}

We are not passing any optional parameters like sync validations or async validations, but we will explore these parameters while adding validation to a FormControl.

On the View, you can use email FormControl as shown below:

<input [formControl]='email'
       type="text"
       placeholder="Enter Email" />
{{email.value | json}}

As you see, we are using property binding to bind the formControl email to the input element on the view.

Step 4: Using FormGroup Class

FormGroupis a group of FormControls. You can encapsulate various FormControls inside a FormGroup, which offers an API for:

  1. Tracking the validation of a group of controls or form.
  2. Tracking the value of a group of controls or form.

It contains child controls as its property and it corresponds to the top lever form on the view. You can think of a FormGroup as a single object, which aggregates the values of child FormControl. Each individual form control is the property of the FormGroup object.

You can create a FormGroup class as shown in the below code:

loginForm = new FormGroup({
    email: new FormControl(' '),
    password: new FormControl(' ')
})

Here we have created a login form, which is a FormGroup. It consists of two form controls for email and password. It is very easy to use FormGroup on the view as shown in the following code:

<form [formGroup]='loginForm' novalidate class="form">
    <input formControlName='email'
           type="text"
           class="form-control"
           placeholder="Enter Email" />
    <input formControlName='password'
           type="password"
           class="form-control"
           placeholder="Enter Password" />
</form>
{{loginForm.value | json}}
{{loginForm.status | json }}

Here we're using property binding to bind FormGroup with the form and the formControlName directive to attach FormControl to a particular element on the view.

If you have used a template driven form, you will notice that the view is much leaner now: there is no ngModel or name attached to the elements. You can find the value and status of the form by using the value and status property. Now, you no longer need to use a template reference variable to find the status and value of the form.

Step 5: Submitting a Form

To submit the form, let's add a submit button on the form and a function to be called. We'll modify the form as below:

<form (ngSubmit)='loginUser()' [formGroup]='loginForm' novalidate class="form">
    <input formControlName='email' type="text" class="form-control" placeholder="Enter Email" />
    <input formControlName='password' type="password" class="form-control" placeholder="Enter Password" />
    <button class="btn btn-default">Login</button>
</form>

In the component class, you can add a function to submit the form as shown in the below code:

export class AppComponent implements OnInit {

    loginForm: FormGroup;
    ngOnInit() {
        this.loginForm = new FormGroup({
            email: new FormControl(null, Validators.required),
            password: new FormControl()
        });
    }
    loginUser() {
        console.log(this.loginForm.status);
        console.log(this.loginForm.value);
    }
}

Here we've just added a function called loginUser to handle the form submit event. Inside this function, you can read the value and status of the FormGroup object loginForm using the status and value properties. As you can see, this gives you an object which aggregates the values of individual form controls.

Step 6: Adding Validations

You may have noticed that we haven't added any validation to the forms. Let us start by adding a validation to FormControl. To do so, import Validators from @angular/forms:

ngOnInit() {
    this.loginForm = new FormGroup({
        email: new FormControl(null, Validators.required),
        password: new FormControl(null, [Validators.required, Validators.maxLength(8)])
    });
}

On the template, you can use the FormGroup get method to find an error in a particular form control and use it. In the listing below, we are checking the validation error for an email and displaying the error div.

You can also disable your submit button by default, and enable it when the form is valid to allow for submission. This can be done as shown below:

<button [disabled]='loginForm.invalid' class="btn btn-default">Login</button>

Putting everything together, the template with reactive forms will look like the following:

<div class="container">
    <br />
    <form (ngSubmit)='loginUser()' [formGroup]='loginForm' novalidate class="form">
        <input formControlName='email' type="text" class="form-control" placeholder="Enter Email" />
        <div class="alert  alert-danger" *ngIf="loginForm.get('email').hasError('required') && loginForm.get('email').touched">
            Email is required
        </div>
        <input formControlName='password' type="password" class="form-control" placeholder="Enter Password" />
        <div class="alert  alert-danger" *ngIf=" !loginForm.get('password').valid && loginForm.get('email').touched">
            Password is required and should less than 10 characters
        </div>
        <button [disabled]='loginForm.invalid' class="btn btn-default">Login</button>
    </form>
</div>

The component class will be as shown below:

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, FormArray, Validators } from '@angular/forms';
@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
 
    loginForm: FormGroup;
 
    ngOnInit() {
 
        this.loginForm = new FormGroup({
            email: new FormControl(null, [Validators.required, Validators.minLength(4)]),
            password: new FormControl(null, [Validators.required, Validators.maxLength(8)])
        });
    }
    loginUser() {
        console.log(this.loginForm.status);
        console.log(this.loginForm.value);
    }
}

Step 6: Using FormBuilder

FormBuilder is used to simplify the syntax for FormGroup and FormControl. This is very useful when your form gets lengthy. Let's refactor loginForm to use FormBuilder. To do so, first import FormBuilder from @angular/forms. Then inject it to the component as shown below:

constructor(private fb : FormBuilder){

}

You can use FormBuilder to create a reactive form as shown in the listing below. As you see, it has simplified the syntax:

this.loginForm = this.fb.group({
    email: [null, [Validators.required, Validators.minLength(4)]],
    password: [null, [Validators.required, Validators.maxLength(8)]]

})

The template will be the same for both FormBuilder and FormControl classes. Putting everything together, the component using FormBuilder to create a reactive form will look like this:

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, FormArray, Validators, FormBuilder } from '@angular/forms';
@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {

    loginForm: FormGroup;

    constructor(private fb: FormBuilder) {

    }
    ngOnInit() {

        this.loginForm = this.fb.group({
            email: [null, [Validators.required, Validators.minLength(4)]],
            password: [null, [Validators.required, Validators.maxLength(8)]]

        })
    }

    loginUser() {
        console.log(this.loginForm.status);
        console.log(this.loginForm.value);
    }
}
Form (document) AngularJS Template

Published at DZone with permission of Dhananjay Kumar, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • The Most Popular Angular UI Libraries To Try in 2021
  • Recursive Angular Rendering of a Deeply Nested Travel Gallery
  • 50+ Top Angular Interview Questions and Answers
  • Create a Beautiful Login Form With Angular Material

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!