How To Create Reusable Reactive Form in Angular

While designing a login form, for instance, there may be instances where you need to reuse it for other components.

How to develop a reactive form that can be used across different components that is scalable, versatile, etc.

In order to construct an adaptable and reusable Angular Reactive Form that adheres to best practises, follow the guidelines below. Here, we’ll construct a registration form.

To store form keys and constants, create a constant file.

Now, let’s create a constant file with the name app.constant.ts in the src folder. Provide the key names for your signup form in the constant file in the manner shown below.

export const AppConstant = {
    forms: {
        signup: {
            name: {
                control: 'name',
                label: 'Name'
            },
            email: {
                control: 'email',
                label: 'Email'
            },
            password: {
                control: 'password',
                label: 'Password'
            },
            dob: {
                control: 'dob',
                label: 'Date Of Birth'
            },
            address: {
                control: 'address',
                label: 'Address'
            },
            pincode: {
                control: 'pincode',
                label: 'Pin Code'
            }
        },
        errors: {
            datePicker: {
                required: {
                    message: 'This field is required and date format in mm/dd/yyyy'
                },
                notRequird: {
                    message: 'Invalid date Format and date format in mm/dd/yyyy'
                },
                format: {
                    message: 'MM/DD/YYYY'
                }
            }
        } 
    }
}

Making use of the Typescript interface, create a User Model

export interface User {
    name: string,
    email: string,
    password: string,
    dob: string,
    address: string,
    pincode: string
}

Create a comman service

ng g s common

After creating the common service, we must next develop the signup form within the common service. To do this, we will utilise the root component, AppComponent, to build the Angular Reactive Form.

To construct the form using FormBuilder, we will write the following code.

createSignupForm(): FormGroup {
   return this.fb.group({
     [AppConstant.forms.signup.name.control]: ['', Validators.required],
     [AppConstant.forms.signup.email.control]: ['', Validators.required],
     [AppConstant.forms.signup.password.control]: ['', Validators.required],
     [AppConstant.forms.signup.dob.control]: [''],
     [AppConstant.forms.signup.address.control]: ['', Validators.required],
     [AppConstant.forms.signup.pincode.control]: ['', Validators.required]
    });
}

In the root component (app component), create a reactive form:

Now that the reactive form must be created in the root component, let’s do it in the app.component.ts file and reuse the common service form.

export class AppComponent implements OnInit {
  signupForm?: FormGroup;
 
  constructor(private commonService: CommonService) { }

  get appConstant() {
    return AppConstant
  }
  
  ngOnInit(): void {
    this.createSignupForm();
  }

  createSignupForm(): void {
    this.signupForm = this.commonService.createSignupForm();
  }

  onSubmit(isValid: boolean, payload: User): void {
      if (isValid) {
        ...Do the Signup Api Call
      }
  }
}

When the signup form is constructed in the app.component.ts file, we must now build the equivalent html file (app.component.html) in order to link the signupForm to the view layer.

<form [formGroup]="signupForm" (ngSubmit)="onSubmit(signupForm.valid, signupForm.value)">
    <div class="grid pt-3">
        <div class="col-12 sm:col-12 md:col-4 lg:col-4 xl:col-4">
              <mat-form-field >
                <mat-label>{{appConstant.forms.signup.name.label}}</mat-label>
                <input type="text" matInput [formControlName]="appConstant.forms.signup.name.control">
                <mat-error *ngIf="signupForm.controls[appConstant.forms.signup.name.control].hasError('required')">
                    This field is <strong>required</strong>
                </mat-error>
            </mat-form-field>
       </div>

      
        <div class="col-12 sm:col-12 md:col-4 lg:col-4 xl:col-4">
                <mat-form-field >
                    <mat-label>{{appConstant.forms.signup.email.label}}</mat-label>
                    <input type="email" matInput [formControlName]="appConstant.forms.signup.email.control">
                    <mat-error *ngIf="signupForm.controls[appConstant.forms.signup.email.control].hasError('required')">
                        This field is <strong>required</strong>
                    </mat-error>
                </mat-form-field>
        </div>

        <div class="col-12 sm:col-12 md:col-4 lg:col-4 xl:col-4">
            <mat-form-field >
                <mat-label>{{appConstant.forms.signup.password.label}}</mat-label>
                <input type="password" matInput [formControlName]="appConstant.forms.signup.password.control">
                <mat-error *ngIf="signupForm.controls[appConstant.forms.signup.password.control].hasError('required')">
                    This field is <strong>required</strong>
                </mat-error>
            </mat-form-field>
        </div>

        <div class="col-12 sm:col-12 md:col-4 lg:col-4 xl:col-4">
            <mat-form-field>
                <mat-label>{{appConstant.forms.signup.dob.label}}</mat-label>
                <input matInput [matDatepicker]="dob" appFormatDate [formControlName]="appConstant.forms.signup.dob.control">
                <mat-hint>{{appConstant.forms.errors.datePicker.format.message}}</mat-hint>
                <mat-datepicker-toggle matSuffix [for]="dob"></mat-datepicker-toggle>
                <mat-datepicker #dob></mat-datepicker>
                <mat-error>
                    {{appConstant.forms.errors.datePicker.notRequird.message}}
                </mat-error>
            </mat-form-field>
        </div>

        <div class="col-12 sm:col-12 md:col-4 lg:col-4 xl:col-4">
            <mat-form-field >
                <mat-label>{{appConstant.forms.signup.address.label}}</mat-label>
                <input type="text" matInput [formControlName]="appConstant.forms.signup.address.control">
                <mat-error *ngIf="signupForm.controls[appConstant.forms.signup.address.control].hasError('required')">
                    This field is <strong>required</strong>
                </mat-error>
            </mat-form-field>
        </div>

        <div class="col-12 sm:col-12 md:col-4 lg:col-4 xl:col-4">
            <mat-form-field >
                <mat-label>{{appConstant.forms.signup.pincode.label}}</mat-label>
                <input type="number" matInput [formControlName]="appConstant.forms.signup.pincode.control">
                <mat-error *ngIf="signupForm.controls[appConstant.forms.signup.pincode.control].hasError('required')">
                    This field is <strong>required</strong>
                </mat-error>
            </mat-form-field>
        </div>
   
        <div class="grid">
            <div class="col-12 sm:col-12 md:col-12 lg:col-12 xl:col-12 text-right">
                <div class="signup-buttons">
                    <button type="submit" [disabled]="!signupForm.valid" mat-raised-button color="primary">Register</button>
                </div>
            </div>
        </div>
  
  </form>

 

 

 

Submit a Comment

Your email address will not be published. Required fields are marked *

Subscribe

Select Categories