The Wayback Machine - http://web.archive.org/web/20201101084910/https://github.com/dinanathsj29/angular-forms-reactive-tutorial
Skip to content
master
Go to file
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 

README.md

Angular logo

Angular Reactive Forms (Model driven)

Working with existing/cloned/copied Angular App

  • Clone or Download the project/app from Github or any other sources
  • If using Visual Studio Code / Insiders, open Command panel/terminal from menu: View -> Terminal (shortcut key is CTRL + BackTick OR COMMAND + J)
  • Go inside the project/app directory, command: cd _examples-angular-templateDrivenForm OR cd templateDrivenForm
  • Run command: npm install to install project/app dependencies (node_modules)
  • To Build and run Angular App, command: ng serve / npm start OR ng serve -o OR ng serve --open
  • To change the port from 4200 to other port - type command: ng serve --port 5000
  • To check the application in browser type path/URL: localhost:4200 / 5000

1.1. Reactive Model Driven Forms

We know that:

  • Reactive forms give the ability to control validation from the component code
  • Also, we are able to do a unit test of reactive model-driven forms

1.2. Setup Angular Project

  1. Create a new Angular project with command at the console: ng new angular-reactive-forms-tutorial
  2. Change Directory and get inside the directory with the command: cd angular-reactive-forms-tutorial and check angular app folder structure

   

Angular project/app folder structure

    Image - Angular project/app folder structure

  1. Run/Serve/Build Angular application with the command: ng serve or ng serve -o or ng serve --open
    • -o or --open flag directly launch the application into default browser (default port is 4200)
    • One can also change the port number by using the command: ng serve --port 5000 -o
  2. Go to browser and type: http://localhost:5000 to launch an angular application

   

Angular default app launch

    Image - Angular default app launch

1.3. Constructing HTML Form structure

  1. In Index.html file, in head element, link/import/include any front-end UI framework like Bootstrap or Zurb Foundation which helps to easily style our app/form layout

Syntax & Example: index.html

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.3.1/css/foundation.min.css">

or

<!-- link/import/include zurb foundation -->
<link rel="stylesheet" href="./assets/library/foundation.min.css">
  1. To verify the Zurb Foundation included/working properly in an application, check the angular app in browser fonts, etc changed?
    • Right click on page/element and check in inspect element the Zurb Foundation classes and properties applied to respective elements:

   

Zurb Foundation framework styly applied

    Image - Zurb Foundation framework styly applied

  1. From file app.component.html delete all old code and add new markup to create form:

Syntax & Example: app.component.html

<!-- show this template if name property not exist or form not submitted -->
<div *ngIf="!name; else formsubmitdata">

  <form>

    <div class="form-container">

      <div class="row columns">
        
        <h1>Beginners Simple Reactive Form</h1>

        <!-- name -->
        <label>Name
          <input type="text" placeholder="Enter Name">
        </label>

        <!-- description -->
        <label>Description
          <textarea placeholder="Enter Description"></textarea>
        </label>

        <!-- checkbox -->
        <label for="validate">Minimum of 5 Characters Name required</label>
        <input type="checkbox" name="validate" value="1"> ON

        <!-- submit button -->
        <input type="submit" class="button expanded" value="Submit Form">

      </div>

    </div>

  </form>

</div>

<!-- show this template if name property exists or form submitted -->
<ng-template #formsubmitdata>

  <div class="form-container">

    <div class="row columns">

      <h1>You Entered Name: {{ name }}</h1>

      <p>Your Description Details: {{ description }}</p>

    </div>

  </div>
  
</ng-template>

   

Simple HTML Form with Zurb Foundation

    Image - Simple HTML Form with Zurb Foundation

1.4. Styling HTML Form with CSS

  • With the Zurb Foundation framework some styling applied, let us create some custom css style to make form/interface more attractive and intuative

Syntax & Example: styles.css

/* You can add global styles to this file, and also import other style files */

/* apply google font family */
@import url('https://fonts.googleapis.com/css?family=ZCOOL+XiaoWei');

body {
  background:rgba(148, 134, 93, 0.35);;
  /* font-family: 'ZCOOL XiaoWei', serif !important; */
}

* {
  font-family: 'ZCOOL XiaoWei', serif !important;
}

.form-container {
  display:block;
  width:90%;
  padding:2em;
  margin: 2em auto;
  background:#fff;
}

h1 {
  text-align: center;
  margin-bottom: 1rem;
  font-weight:bold;
}

.button {
  margin-top: 1rem;
  font-weight: bold;
}

/* error text message alert */
.alert {
  background: #f2dada;
  padding: 5px;
  font-size: .9em;
  margin-bottom: 15px;
  display: inline-block;
  animation: 2s alertAnim forwards;
}

/* animation effect for error text message alert */
@keyframes alertAnim {
  from {
    opacity:0;
    transform: translateY(-20px);
  }
  to {
    opacity:1;
    transform: translateY(0);
  }
}

   

CSS Style applied HTML Form

    Image - CSS Style applied HTML Form

1.5. Integrating Rective Form Class

  • To work with reactive/dynamic forms we need to import 'ReactiveFormsModule' which provides bunch of classes/directives/utilities necessary to build reactive/dynamic forms
  1. In app.module.ts: import { ReactiveFormsModule } from '@angular/forms';
    • also add to imports: [ ReactiveFormsModule ]

Syntax & Example: app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { ReactiveFormsModule } from '@angular/forms';

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

1.6. Composing Component Class with ReactiveForms building blocks

  • FormGroup and FormControl are two important building blocks classes for reactive/dynamic forms
    • In Reactive forms, the form is represented by model in component class, FormGroup and FormControl classes used to make that model
    • FormGroup represents whole/entire form ( form is instance of FormGroup class )
    • FormControl represents each form field ( form fields are instance of FormControl class )
    • FormBuilder handle form control creation, dynamic/run time field/FormControl creation
    • Validators helps to setup validation on each form control
  1. In app.component.ts import { FormBuilder, FormGroup, Validators } from '@angular/forms'; and write following logical code to build reactive form

Syntax & Example: app.component.ts

import { Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent {

  simpleBegReactiveForm: FormGroup;     // form
  formSubmitPost: any;                  // A property for our submitted form
  name: string = '';                    // name text
  description: string = '';             // description text

  // create a FormBuilder dependecy injection
  constructor(private fb: FormBuilder) {

    // reference FormBuilder instance to control the validation of each form field
    this.simpleBegReactiveForm = fb.group({
      'name': ['', Validators.required],
      'description': ['', [Validators.required, Validators.minLength(30), Validators.maxLength(100)]],
      'validate': ''
    });

  }

  // handler to submit form
  submitFormData(formSubmitPost) {
    this.description = formSubmitPost.description;
    this.name = formSubmitPost.name;
  }

}

1.7. Update HTML Form (bind Model with View)

  • Lets use and apply class members created in app.component.ts for specific field/controls and bind with form and input fields, ([formGroup]="simpleBegReactiveForm", formControlName="name" ...)

Syntax & Example: app.component.html

<!-- show this template if name property not exist or form not submitted -->
<div *ngIf="!name; else formsubmitdata">

  <!-- associate the model with view -->
  <form [formGroup]="simpleBegReactiveForm" (ngSubmit)="submitFormData(simpleBegReactiveForm.value)">

    <div class="form-container">

      <div class="row columns">
        
        <h1>Beginners Simple Reactive Form</h1>

        <!-- name -->
        <label>Name
          <input type="text" placeholder="Enter Name" formControlName="name">
        </label>

        <!-- description -->
        <label>Description
          <textarea formControlName="description"></textarea>
        </label>

        <!-- checkbox -->
        <label for="validate">Minimum of 5 Characters Name required</label>
        <input type="checkbox" name="validate" value="1" formControlName="validate" > ON

        <!-- submit button -->
        <input type="submit" class="button expanded" value="Submit Form" [disabled]="!simpleBegReactiveForm.valid">

      </div>

    </div>

  </form>

</div>

   

Bind Model with View

    Image - Bind Model with View

1.8. Adding/Showing Validation Messages

  • Now add required validation message text as a alert and use interpolation to show class member

Syntax & Example: app.component.html

<!-- show name alert text -->
<div class="alert" *ngIf="!simpleBegReactiveForm.controls['name'].valid && simpleBegReactiveForm.controls['name'].touched">{{ titleAlertText }}</div>

<!-- show name description text -->
<div class="alert" *ngIf="!simpleBegReactiveForm.controls['description'].valid && simpleBegReactiveForm.controls['description'].touched">{{ descriptionAlertText }}</div>

Syntax & Example: app.component.ts

titleAlertText = 'Name field is required';
descriptionAlertText = 'Specify Description between 30 to 100 characters';

   

Shwoing alert error message text

    Image - Shwoing alert error message text

1.9. Implement Dyanmic Validation with checkbox

  • Sometimes we need to perform form validation based on user input
  • Like in current form, If checkbox is ON than Name must required with 5 characters else any characters
  • We need to track value of checkbox and conditionaly set status of other field
    • valueChanges property helps to track the current value of any controls as a observables
    • setValidators methods - set desired validators to formControl/field
    • clearValidators methods - clears validators from formControl/field
  • Finally we need to invoke/call updateValueAndValidity method to reflect latest status

Syntax & Example: app.component.ts

ngOnInit() {

  // subscribe checkbox
  this.simpleBegReactiveForm.get('validate').valueChanges.subscribe(

  (validate) => {

    if (validate == '1') {
      // name field set/unset `required` validators
      this.simpleBegReactiveForm.get('name').setValidators([Validators.required, Validators.minLength(5)]);
      this.titleAlertText = 'Specify Name with 5 characters';
    } else {
      this.simpleBegReactiveForm.get('name').setValidators(Validators.required);
      this.titleAlertText = 'Name field is required';
    }
    // to reflect latest correct status
    this.simpleBegReactiveForm.get('name').updateValueAndValidity();

  });
}

   

Checkbox dynamic validator error

    Image - Checkbox dynamic validator error


   

Checkbox dynamic validator success

    Image - Checkbox dynamic validator success


   

Submit Data success screen

    Image - Submit Data success screen

1.10. Final working code

Syntax & Example: index.html

<!doctype html>
  <html lang="en">

    <head>
      <meta charset="utf-8">
      <title>AngularReactiveFormsTutorial</title>
      <base href="/">

      <meta name="viewport" content="width=device-width, initial-scale=1">
      <link rel="icon" type="image/x-icon" href="favicon.ico">

      <!-- link/import/include zurb foundation -->
      <link rel="stylesheet" href="./assets/library/foundation.min.css">

    </head>

    <body>
      <app-root></app-root>
    </body>
    
  </html>

Syntax & Example: app.component.html

<!-- show this template if name property not exist or form not submitted -->
<div *ngIf="!name; else formsubmitdata">

  <!-- associate the model with view -->
  <form [formGroup]="simpleBegReactiveForm" (ngSubmit)="submitFormData(simpleBegReactiveForm.value)">

    <div class="form-container">

      <div class="row columns">
        
        <h1>Beginners Simple Reactive Form</h1>

        <!-- name -->
        <label>Name
          <input type="text" placeholder="Enter Name" formControlName="name">
        </label>

        <!-- show name alert text -->
        <div class="alert" *ngIf="!simpleBegReactiveForm.controls['name'].valid && simpleBegReactiveForm.controls['name'].touched">{{ titleAlertText }}</div>

        <!-- description -->
        <label>Description
          <textarea formControlName="description"></textarea>
        </label>
        
        <!-- show name description text -->
        <div class="alert" *ngIf="!simpleBegReactiveForm.controls['description'].valid && simpleBegReactiveForm.controls['description'].touched">{{ descriptionAlertText }}</div>

        <!-- checkbox -->
        <label for="validate">Minimum of 5 Characters Name required</label>
        <input type="checkbox" name="validate" value="1" formControlName="validate" > ON

        <!-- submit button -->
        <input type="submit" class="button expanded" value="Submit Form" [disabled]="!simpleBegReactiveForm.valid">

      </div>

    </div>

  </form>

</div>

<!-- show this template if name property exists or form submitted -->
<ng-template #formsubmitdata>

  <div class="form-container">

    <div class="row columns">

      <h2>You Entered Name: {{ name }}</h2>

      <p>Your Description Details: {{ description }}</p>

    </div>

  </div>
  
</ng-template>

Syntax & Example: styles.css

/* You can add global styles to this file, and also import other style files */

/* apply google font family */
@import url('https://fonts.googleapis.com/css?family=ZCOOL+XiaoWei');

body {
  background:rgba(148, 134, 93, 0.35);;
  /* font-family: 'ZCOOL XiaoWei', serif !important; */
}

* {
  font-family: 'ZCOOL XiaoWei', serif !important;
}

.form-container {
  display:block;
  width:90%;
  padding:2em;
  margin: 2em auto;
  background:#fff;
}

h1 {
  text-align: center;
  margin-bottom: 1rem;
  font-weight:bold;
}

.button {
  margin-top: 1rem;
  font-weight: bold;
}

/* error text message alert */
.alert {
  background: #f2dada;
  padding: 5px;
  font-size: .9em;
  margin-bottom: 15px;
  display: inline-block;
  animation: 2s alertAnim forwards;
}

/* animation effect for error text message alert */
@keyframes alertAnim {
  from {
    opacity:0;
    transform: translateY(-20px);
  }
  to {
    opacity:1;
    transform: translateY(0);
  }
}

Syntax & Example: app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { ReactiveFormsModule } from '@angular/forms';

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

Syntax & Example: app.component.ts

import { Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent {

  simpleBegReactiveForm: FormGroup;     // form
  formSubmitPost: any;                  // A property for our submitted form
  name: string = '';                    // name text
  description: string = '';             // description text

  titleAlertText = 'Name field is required';
  descriptionAlertText = 'Specify Description between 30 to 100 characters';

  // create a FormBuilder dependecy injection
  constructor(private fb: FormBuilder) {

    // reference FormBuilder instance to control the validation of each form field
    this.simpleBegReactiveForm = fb.group({
      'name': ['', Validators.required],
      'description': ['', [Validators.required, Validators.minLength(30), Validators.maxLength(100)]],
      'validate': ''
    });

  }

  // handler to submit form
  submitFormData(formSubmitPost) {
    this.description = formSubmitPost.description;
    this.name = formSubmitPost.name;
  }
  
  ngOnInit() {

    // subscribe checkbox
    this.simpleBegReactiveForm.get('validate').valueChanges.subscribe(

    (validate) => {

      if (validate == '1') {
        // name field set/unset `required` validators
        this.simpleBegReactiveForm.get('name').setValidators([Validators.required, Validators.minLength(5)]);
        this.titleAlertText = 'Specify Name with 5 characters';
      } else {
        this.simpleBegReactiveForm.get('name').setValidators(Validators.required);
        this.titleAlertText = 'Specify Name with 5 characters';
      }
      // to reflect latest correct status
      this.simpleBegReactiveForm.get('name').updateValueAndValidity();

    });
  }

}

About

Lets have a quick overview of Angular's Reactive Model Driven Forms with live practical example.

Topics

Resources

Releases

No releases published

Packages

No packages published
You can’t perform that action at this time.