Form
ReactiveFormsModule
ReactiveFormsModule
is a module provided by Angular to create and manage Reactive Forms, allowing us to control and update the values and validation state of a form directly from the component class. Dynamic forms using ReactiveFormsModule
can dynamically add or remove form controls based on business requirements.
1. Preparation
First, make sure that ReactiveFormsModule
has been imported into your Angular module.
Step 1: Import ReactiveFormsModule
in the module
Add ReactiveFormsModule
to your module file app.module.ts
to ensure that your components can use the responsive forms functionality.
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ReactiveFormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
ReactiveFormsModule // import ReactiveFormsModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
2. Creating a Dynamic Form Component
We will create a simple dynamic form component that allows users to dynamically add and remove form controls. Step 2: Create Component Create a new component using Angular CLI with the following command:
ng generate component dynamic-form
Step 3: Implementing Dynamic Form Logic
In the generated component file, use FormBuilder
and FormArray
to create dynamic forms.
- **
FormBuilder
**: used to simplify the form creation process. 2. **FormArray
**: used to create the dynamic form. FormArray
: used to manage an array of form controls for dynamic forms. Indynamic-form.component.ts
:
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, FormArray, Validators } from '@angular/forms';
@Component({
selector: 'app-dynamic-form',
templateUrl: './dynamic-form.component.html',
styleUrls: ['./dynamic-form.component.css']
})
export class DynamicFormComponent {
myForm: FormGroup;
constructor(private fb: FormBuilder) {
// Initialize the form and create an empty FormArray
this.myForm = this.fb.group({
items: this.fb.array([]) // items is a FormArray
});
}
// Get the items array
get items(): FormArray {
return this.myForm.get('items') as FormArray;
}
}
// Dynamically add new controls
addItem(): void {
const itemForm = this.fb.group({
name: ['', Validators.required], // Name control
quantity: [1, [Validators.required, Validators.min(1)]] // Quantity control, minimum value is 1
});
this.items.push(itemForm); // Add to FormArray
}
// Dynamically remove controls
removeItem(index: number): void {
this.items.removeAt(index); // Remove controls from FormArray
}
3. Create the HTML template for the dynamic form
In dynamic-form.component.html
:
<form [formGroup]="myForm" (ngSubmit)="onSubmit()">
<div formArrayName="items">
<div *ngFor="let item of items.controls; let i = index" [formGroupName]="i" style="margin-bottom: 1em;">
<label>
Name:
<input formControlName="name" placeholder="Item name">
</label>
<label>
Quantity:
<input type="number" formControlName="quantity" placeholder="Quantity">
</label>
<button type="button" (click)="removeItem(i)">Remove</button>
</div>
</div>
<button type="button" (click)="addItem()">Add Item</button>
<button type="submit" [disabled]="myForm.invalid">Submit</button>
</form>
4. Run the code and test
Test steps:
-
Open the Angular application and navigate to the route where the dynamic form component is located.
-
Click the "Add Item" button to add a new input box for the user to enter the name and quantity of the item.
-
Fill in the form content and click "Submit" to submit the form.
-
Check the console and the form value will be printed out.
Summary
-
FormArray
allows us to create an array of controls that can be added or deleted dynamically, which is very suitable for dynamic forms. -
FormBuilder
makes form creation more concise. -
Validators
is used to set validation conditions for form controls to ensure that user input meets the requirements.
FormGroup
In Angular, FormGroup
is a class used to group multiple form controls into a group, which is convenient for managing and validating these controls. A FormGroup
can contain multiple FormControl
and treat them as a whole, which is very suitable for complex form structures.
Below is the detailed code and steps on how to create a form using FormGroup
.
1. Preparation
Make sure that ReactiveFormsModule
has been imported in the Angular project to use the responsive form function.
Import ReactiveFormsModule
in app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ReactiveFormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
ReactiveFormsModule // Import ReactiveFormsModule to support responsive forms
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
2. Create a form component
Create a new component to implement the form functionality. Suppose we create a registration form component with "username", "password" and "email" fields.
Use Angular CLI to create a new component
ng generate component registration-form
3. Create FormGroup
in the component
In registration-form.component.ts
, create a form using FormGroup
and FormControl
and initialize these controls in the constructor.
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
@Component({
selector: 'app-registration-form',
templateUrl: './registration-form.component.html',
styleUrls: ['./registration-form.component.css']
})
export class RegistrationFormComponent implements OnInit {
registrationForm: FormGroup;
constructor() {
// Initialize FormGroup and define each form control
this.registrationForm = new FormGroup({
username: new FormControl('', [Validators.required, Validators.minLength(3)]), // Username control, required, at least 3 characters
password: new FormControl('', [Validators.required, Validators.minLength(6)]), // Password control, required, at least 6 characters
email: new FormControl('', [Validators.required, Validators.email]) // Email control, required, must conform to email format
});
}
ngOnInit(): void {}
onSubmit(): void {
if (this.registrationForm.valid) {
// Process valid form data
console.log('Form submitted:', this.registrationForm.value);
} else {
// Prompt error when the form is invalid
console.log('Form is invalid');
}
}
}
4. Create the HTML template for the form
In the component template file registration-form.component.html
, use Angular's formGroup
directive to bind the form to registrationForm
and add input boxes for each control.
<form [formGroup]="registrationForm" (ngSubmit)="onSubmit()">
<div>
<label for="username">Username:</label>
<input id="username" formControlName="username">
<div *ngIf="registrationForm.get('username')?.invalid && registrationForm.get('username')?.touched">
<small *ngIf="registrationForm.get('username')?.errors?.['required']">Username is required.</small>
<small *ngIf="registrationForm.get('username')?.errors?.['minlength']">Username must be at least 3 characters long.</small>
</div>
</div>
<div>
<label for="password">Password:</label>
<input type="password" id="password" formControlName="password">
<div *ngIf="registrationForm.get('password')?.invalid && registrationForm.get('password')?.touched">
<small *ngIf="registrationForm.get('password')?.errors?.['required']">Password is required.</small>
<small *ngIf="registrationForm.get('password')?.errors?.['minlength']">Password must be at least 6 characters long.</small>
</div>
</div>
<div>
<label for="email">Email:</label>
<input id="email" formControlName="email">
<div *ngIf="registrationForm.get('email')?.invalid && registrationForm.get('email')?.touched">
<small *ngIf="registrationForm.get('email')?.errors?.['required']">Email is required.</small>
<small *ngIf="registrationForm.get('email')?.errors?.['email']">Please enter a valid email address.</small>
</div>
</div>
<button type="submit" [disabled]="registrationForm.invalid">Register</button>
</form>
5. Validate and submit the form
In the template, each input box has a validation prompt message. The corresponding error prompt is only displayed when the control is touched and the validation fails. After the user fills in the form and passes the validation, the form can be submitted. The form data will be printed out in the console.
Summary
-
FormGroup: Used to combine multiple
FormControl
into a group for unified management and validation. -
FormControl: Represents a single form control, used to receive the value entered by the user.
-
Validators: Provides some commonly used validators, such as
required
,minLength
,email
, etc.
Final code
registration-form.component.ts
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
@Component({
selector: 'app-registration-form',
templateUrl: './registration-form.component.html',
styleUrls: ['./registration-form.component.css']
})
export class RegistrationFormComponent implements OnInit {
registrationForm: FormGroup;
constructor() {
this.registrationForm = new FormGroup({
username: new FormControl('', [Validators.required, Validators.minLength(3)]),
password: new FormControl('', [Validators.required, Validators.minLength(6)]),
email: new FormControl('', [Validators.required, Validators.email])
});
}
ngOnInit(): void {}
onSubmit(): void {
if (this.registrationForm.valid) {
console.log('Form submitted:', this.registrationForm.value);
} else {
console.log('Form is invalid');
}
}
}
registration-form.component.html
<form [formGroup]="registrationForm" (ngSubmit)="onSubmit()">
<div>
<label for="username">Username:</label>
<input id="username" formControlName="username">
<div *ngIf="registrationForm.get('username')?.invalid && registrationForm.get('username')?.touched">
<small *ngIf="registrationForm.get('username')?.errors?.['required']">Username is required.</small>
<small *ngIf="registrationForm.get('username')?.errors?.['minlength']">Username must be at least 3 characters long.</small>
</div>
</div>
<div>
<label for="password">Password:</label>
<input type="password" id="password" formControlName="password">
<div *ngIf="registrationForm.get('password')?.invalid && registrationForm.get('password')?.touched">
<small *ngIf="registrationForm.get('password')?.errors?.['required']">Password is required.</small>
<small *ngIf="registrationForm.get('password')?.errors?.['minlength']">Password must be at least 6 characters long.</small>
</div>
</div>
<div>
<label for="email">Email:</label>
<input id="email" formControlName="email">
<div *ngIf="registrationForm.get('email')?.invalid && registrationForm.get('email')?.touched">
<small *ngIf="registrationForm.get('email')?.errors?.['required']">Email is required.</small>
<small *ngIf="registrationForm.get('email')?.errors?.['email']">Please enter a valid email address.</small>
</div>
</div>
<button type="submit" [disabled]="registrationForm.invalid">Register</button>
</form>
Form processing
In Angular, it is an important part of building interactive user interfaces. In order to effectively manage and validate user input, Angular provides two tools, FormBuilder
and Validators
. The following is a detailed explanation of them.
1. FormBuilder
FormBuilder
is a service in Angular that simplifies the process of creating form controls. It makes the creation of forms more concise and intuitive. FormBuilder
provides some methods that can be used to generate form controls, form groups, and form arrays.
Function and use
-
Creating form controls: Using
FormBuilder
, you can easily create form controls and groups. -
Better readability: By using
FormBuilder
, the structure of the form can be clearer, and the code is easier to understand and maintain.
Sample code
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'app-my-form',
templateUrl: './my-form.component.html',
})
export class MyFormComponent implements OnInit {
myForm: FormGroup;
constructor(private fb: FormBuilder) { } // Inject FormBuilder
ngOnInit(): void {
// Create a form using FormBuilder
this.myForm = this.fb.group({
username: ['', Validators.required], // Create controls and add validators
password: ['', [Validators.required, Validators.minLength(6)]]
});
}
onSubmit(): void {
if (this.myForm.valid) {
// Process a valid form
console.log(this.myForm.value);
} else {
// Process an invalid form
console.log('Form is invalid');
}
}
}
2. Validators
Validators
is a tool class that provides common form validators. It provides a series of static methods that can be used to check whether the input value of the form control meets specific rules.
Function and usage
-
Common validators:
Validators
provides some common validators, such asrequired
,minLength
,maxLength
,pattern
, etc. -
Custom validators: In addition to using built-in validators, developers can also define custom validators to meet specific business needs.
Sample code
import { AbstractControl, ValidationErrors } from '@angular/forms';
// Custom validator example
export function customValidator(control: AbstractControl): ValidationErrors | null {
const forbidden = /admin/.test(control.value); // Check if the input value contains "admin"
return forbidden ? { forbiddenName: { value: control.value } } : null; // Return validation result
}
3. Comprehensive example
Here is a complete example with custom validators, FormBuilder
, and Validators
:
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { customValidator } from './custom-validator'; // Importing a custom validator
@Component({
selector: 'app-registration-form',
templateUrl: './registration-form.component.html',
})
export class RegistrationFormComponent implements OnInit {
registrationForm: FormGroup;
constructor(private fb: FormBuilder) { }
ngOnInit(): void {
this.registrationForm = this.fb.group({
username: ['', [Validators.required, customValidator]], // Use custom validator
password: ['', [Validators.required, Validators.minLength(6)]],
email: ['', [Validators.required, Validators.email]] // Use built-in email validator
});
}
onSubmit(): void {
if (this.registrationForm.valid) {
console.log(this.registrationForm.value);
} else {
console.log('Form is invalid');
}
}
}
Summary
-
FormBuilder
: Used to simplify the creation of form controls, making the form structure clearer and easier to maintain. -
Validators
: Provides built-in common validators and supports custom validators to help developers effectively validate user input. -
Custom validators: Through custom validators, developers can extend validation logic according to business needs and enhance the flexibility and applicability of forms.
By combining FormBuilder
and Validators
, Angular provides a powerful and flexible way to handle form input and validation to ensure the validity of user data.
Custom validation method
FormBuilder
is an auxiliary tool class provided by Angular to simplify the creation of form controls in form components.
Validators
is a tool class that provides common validators for performing validation in form controls.
import { FormControl, FormGroup, FormBuilder, Validators } from '@angular/forms'
constructor(private fb: FormBuilder) { }
valiDataForm: FormGroup = this.fb.group({
userName: [
'',
[Validators.required, Validators.maxLength(18), Validators.minLength(6)],
],
password: ['', [this.passwordVal]],
phone: ['', [Validators.required, this.phoneVal]],
});
passwordVal(password: FormControl): object {
const value = password.value || '';
if (!value) {
return { msg: 'Please enter password' };
} else {
const valid = value.match(/^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,20}$/);
return valid ? {} : { msg: 'The password must contain at least 6 digits or English characters, and the length must be 6-20' };
}
}
phoneVal(phone: FormControl): object {
const value = phone.value || '';
if (!value) return { msg: 'Please enter your phone number' };
const valid = value.match(/[0-9]{11}/);
return valid ? {} : { msg: 'The contact number must be 11 digits' };
}
subFormFunction() {
console.log(this.valiDataForm.get('userName')?.value);
console.log(this.valiDataForm.get('password')?.value);
console.log(this.valiDataForm.get('phone')?.value);
}
Front-end
<form [formGroup]="valiDataForm">
<label>
Account: <input type="text" formControlName="userName" />
</label>
<p *ngIf="valiDataForm.get('userName')?.errors?.['required']">Please enter account number</p>
<p *ngIf="valiDataForm.get('userName')?.errors?.['minlength']?.requiredLength
||valiDataForm.get('userName')?.errors?.['maxlength']?.requiredLength">The account length is between 6-18 digits</p>
<br />
<label>
Password: <input type="text" formControlName="password" />
</label>
<p *ngIf="valiDataForm.get('password')?.errors?.['msg']">{{ valiDataForm.get('password')?.errors?.['msg'] }}</p>
<br />
<label>
Phone Number: <input type="text" formControlName="phone" />
</label>
<p *ngIf="valiDataForm.get('phone')?.errors?.['msg']">{{ valiDataForm.get('phone')?.errors?.['msg'] }}</p>
<br />
<button (click)="subFormFunction()">
Submit
</button>
</form>