Welcome back to the Learn Angular 8 in 10 Days article series - Part 7. In the previous article, we discussed the different concepts of View Encapsulation in Angular. Now, in this article, we will discuss the Concept of Angular Forms; i.e. Template Driven Form and Reactive Form. If you want to read the previous articles of this series, then follow the links.
So, in this article, we will discuss the concept of Forms in Angular 8. Form objects are always the backbone of any web-based application. Because, we can use forms for many purposes within the application like login, submit a request, ask the user to fill in some information, place an order, etc. So, in this article, we will discuss different aspects of Forms object in Angular Framework.
When we want to start developing any web-based application, we always find that a large number of UI or interfaces are very much form dependent. This is very much true for any enterprise-type application also, since most of the interfaces of that application are a large form which contains multiple tabs, dialogs, grid, etc. And also these types of forms always contain non-trivial business validation logic. Since in a component-based framework, we need to split a form into multiple small and reusable pieces of code. These components can be used across the entire application which basically provides many architectural benefits including flexibility and design changes.
Angular 8 deals with the forms of objects through ngModel. The instance two-way data binding technique of ng-model in the Angular framework is really a life-saver, because it provides automatic sync between the form and the view model objects. For using the forms module in Angular, we need to inject the FormModule in our application module.
As a modern full-fledged UI Framework, Angular has its own full-fledged libraries for developing complex form-based UI. The current Angular framework has two types of form-building strategies as,
Both the above technology belongs to the @angular/forms packages and are totally based on the form-control classes. But in spite of that, both the techniques are different from each other in respect to their own philosophy, programming style, and technique.
In the below section, we will discuss in detail items related to the above two types of Angular Forms.
In Angular Framework, Template-driven are those forms where we can write logic, validations, controls, etc. in the HTML template part of the component. Basically, the Template is totally responsible for setting the form elements in the UI, for implementing the validation using form control, etc. With the help of Template, we can also provide the Form Group within the HTML template. Template-driven forms are perfect for the simple scenario-based interface where we can easily use the two-way data binding of Angular. For Template-driven form, Angular provides some form-specific directives which we can use to bind the form input data without model variable. Due to this form-specific directive, we can add extra functionality and behavior to a plain HTML form. In the end, the Template itself takes care of binding the values with the model and the form validation.
In Angular Framework, we can obtain some benefit for using Template-Driven form as below,
Model-Driven form technique is often called a Reactive Form technique in Angular. It provides a model-driven approach to the UI to handling form inputs towards the component variable. Using this technique, we can create and update a simple form of control, progress to using multiple controls within a form group to validate the form control values, etc.
Model-driven or Reactive forms normally use an explicit and immutable approach to manage the state of a form control at any given point of time. If any change occurrs in the form control, then it will return a new state through which Angular can maintain the integrity of the model variables between changes. Basically, reactive forms are normally based on observable streams. So, every form’s input controls and values provide the input value as a stream which is accessed by the reactive form synchronously. With the help of reactive forms, we can perform a straightforward process to perform unit testing on the form controls. This can be done very easily since we can be assured that form data is consistent and predictable whenever requested.
Reactive forms or Model-driven forms are different compared to template-driven forms. Reactive forms always provide more predictability with synchronous access towards the data model variable, provide immutability with observables operators and also keep track of changes using observable streams.
In Angular Framework, we can obtain some benefit for using Model-Driven form or Reactive Form techniques as below,
The comparison between Template-Driven Form and Reactive Forms (Model-Driven Forms) are as below,
FormControl class is mainly used to assign any form related fields in the Angular component. This class is also used in the FormBuilder class method. It is used mainly for ease of access. With the help of references of the FormControl in place of FormControl class, we can gain access to the inputs in the template without using the Form itself. Similarly, we can use any instance of FormControl to access its parent group by using its root property. When we define a form of control, it requires two properties: an initial value and a list of validators.
Angular Framework provides many validators to validate the form control input values in any application. These validations can be imported along with the related dependencies for procedural forms. In general, the common practice for using Form validations are using .valid and .untouched to determine if we need to raise an error message. As an inbuilt validator, we can use hasError() method on the form element to validate the data.
As per the built-in validators, it is very useful if we can create our own custom validator for our purpose. Angular Framework always allows us to do just that, with minimal effort. A simple function takes the FormControl instance and returns null if everything is fine. If the test fails, it returns an object with an arbitrarily named property. In this case, we need to use the property name .hasError() for the test.
<div [hidden]="!password.hasError('hasSpecialChars')">
Your password must have Special Characters like @,#,$, etc!
</div>
Now, in this demo, we will demonstrate how to define a template-driven form in Angular.
app.component.ts
import { Component, OnInit } from '@angular/core';
import { NgForm } from '@angular/forms';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls : ['./custom.css']
})
export class AppComponent implements OnInit {
private formData: any = {};
private showMessage: boolean = false;
constructor() {
}
ngOnInit(): void {
}
registerUser(formdata: NgForm) {
this.formData = formdata.value;
this.showMessage = true;
}
}
app.component.html
<h2>Template Driven Form</h2>
<div>
<form #signupForm="ngForm" (ngSubmit)="registerUser(signupForm)">
<table style="width:60%;" cellpadding="5" cellspacing="5">
<tr>
<td style="width :40%;">
<label for="username">User Name</label>
</td>
<td style="width :60%;">
<input type="text" name="username" id="username" [(ngModel)]="username" required>
</td>
</tr>
<tr>
<td style="width :40%;">
<label for="email">Email</label>
</td>
<td style="width :60%;">
<input type="text" name="email" id="email" [(ngModel)]="email" required>
</td>
</tr>
<tr>
<td style="width :40%;">
<label for="password">Password</label>
</td>
<td style="width :60%;">
<input type="password" name="password" id="password" [(ngModel)]="password" required>
</td>
</tr>
<tr>
<td style="width :40%;"></td>
<td style="width :60%;">
<button type="submit">Sign Up</button>
</td>
</tr>
</table>
</form>
<div *ngIf="showMessage">
<h3>Thanks You {{formData.username}} for registration</h3>
</div>
</div>
Now check the output in the browser,
Now in this demo, we will discuss how to develop a Reactive Form in Angular 8 Framework. For that, we first need to develop a login form component as below –
app.component.ts
import { Component, OnInit, ViewChild } from '@angular/core';
import { Validators, FormBuilder, FormControl, FormGroup } from '@angular/forms';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls : ['./custom.css']
})
export class AppComponent implements OnInit {
private formData: any = {};
username = new FormControl('', [
Validators.required,
Validators.minLength(5)
]);
password = new FormControl('', [
Validators.required,
hasExclamationMark
]);
loginForm: FormGroup = this.builder.group({
username: this.username,
password: this.password
});
private showMessage: boolean = false;
constructor(private builder: FormBuilder) {
}
ngOnInit(): void {
}
registerUser() {
this.formData = this.loginForm.value;
this.showMessage = true;
}
}
function hasExclamationMark(input: FormControl) {
const hasExclamation = input.value.indexOf('!') >= 0;
return hasExclamation ? null : { needsExclamation: true };
}
app.component.html
<h2>Reactive Form Module</h2>
<div>
<form [formGroup]="loginForm" (ngSubmit)="registerUser()">
<table style="width:60%;" cellpadding="5" cellspacing="5">
<tr>
<td style="width :40%;">
<label for="username">User Name</label>
</td>
<td style="width :60%;">
<input type="text" name="username" id="username" [formControl]="username">
<div [hidden]="username.valid || username.untouched" class="error">
<div [hidden]="!username.hasError('minlength')">
Username can not be shorter than 5 characters.
</div>
<div [hidden]="!username.hasError('required')">
Username is required.
</div>
</div>
</td>
</tr>
<tr>
<td style="width :40%;">
<label for="password">Password</label>
</td>
<td style="width :60%;">
<input type="password" name="password" id="password" [formControl]="password">
<div [hidden]="password.valid || password.untouched" class="error">
<div [hidden]="!password.hasError('required')">
The password is required.
</div>
<div [hidden]="!password.hasError('needsExclamation')">
Your password must have an exclamation mark!
</div>
</div>
</td>
</tr>
<tr>
<td style="width :40%;"></td>
<td style="width :60%;">
<button type="submit" [disabled]="!loginForm.valid">Log In</button>
</td>
</tr>
</table>
</form>
<div *ngIf="showMessage">
<h3>Thanks You {{formData.username}} for registration</h3>
</div>
</div>
Now, for using the reactive form we need to inject ReactiveFormModule in our app.module.ts file as below –
import { BrowserModule } from '@angular/platform-browser';
import { NgModule, NO_ERRORS_SCHEMA } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule, FormsModule, ReactiveFormsModule
],
providers: [],
bootstrap: [AppComponent],
schemas: [NO_ERRORS_SCHEMA]
})
export class AppModule { }
Now check the output in the browser,
In this article, we discussed another important feature of Angular Framework i.e. Angular Form. Also, we discussed the Template Driven Forms and Reactive Forms (Model-Driven Form). Now, in the next article, we will discuss the concept of Service in Angular. I hope, this article will help you. Any feedback or query related to this article is most welcome.
Next Article …
#angular #angular8 #learn angular 8 #javascript #tutorial