DEV Community

loading...
Cover image for Reactive Forms : Angular

Reactive Forms : Angular

Rohith V
Full Stack Engineer || Java || Graduated From Government Engineerig College Thrissur. Interested in Data Structures in Java
・3 min read

Objective

Create a Form with the following Controls and Validators
1) Project Name (should not be empty)
2) Mail (should not be a empty and a valid email)
3) Project Status Dropdown, with three values: 'Stable', 'Critical', 'Finished'
4) Submit Button
Add your own Validator which doesn't allow "Test" as a Project Name
Also implement that Validator as an async Validator (replace the other one)
Upon submitting the form, simply print the value to the console

Code

  • app.module.ts - ReactiveFormsModule is important here
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';


import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    ReactiveFormsModule,
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
Enter fullscreen mode Exit fullscreen mode
  • app.component.ts
import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { ProjectNameValidator } from './projectname-validator';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit{
  projectStatus = ['Stable', 'Critical', 'Finished']

  contactForm = new FormGroup({
    projectName: new FormControl('', [Validators.required, ProjectNameValidator.invalidProjectName], ProjectNameValidator.asyncInvalidProjectName),
    emailId: new FormControl('', [Validators.required, Validators.email]),
    projectDetails: new FormControl('Critical')
  });

  onSubmit() {
    console.log(this.contactForm.value);
  }

  get projectName() {
    return this.contactForm.get('projectName');
  }

  get emailId() {
    return this.contactForm.get('emailId');
  }

  get projectDetails() {
    return this.contactForm.get('projectDetails');
  }

  ngOnInit(){

  }
}
Enter fullscreen mode Exit fullscreen mode
  • app.component.html
<div class="container">
  <div class="row">
    <div class="col-xs-12 col-sm-10 col-md-8 col-sm-offset-1 col-md-offset-2">
      <!--
          Create a Form with the following Controls and Validators
          1) Project Name (should not be empty)
          2) Mail (should not be a empty and a valid email)
          3) Project Status Dropdown, with three values: 'Stable', 'Critical', 'Finished'
          4) Submit Button

          Add your own Validator which doesn't allow "Test" as a Project Name

          Also implement that Validator as an async Validator (replace the other one)

          Upon submitting the form, simply print the value to the console
      -->
      <form [formGroup]="contactForm" (ngSubmit)="onSubmit()" novalidate>
        <div class="form-group">
          <label for="project">ProjectName</label>
          <input type="text" id="projectName" name="projectName" class="form-control" formControlName="projectName">
          <div class="alert alert-danger" role="alert" *ngIf="!projectName.valid && (projectName.dirty || projectName.touched)">
            <div class="alert alert-danger" *ngIf="projectName.errors.required">
              Project Name is required, Please enter a valid one. Thank you
            </div>
            <div class="alert alert-danger" *ngIf="projectName.errors.invalidProjectName">
              Project Name is should not be Test
            </div>
            <div class="alert alert-danger" *ngIf="projectName.errors.asyncInvalidProjectName">
              Project Name is should not be test
            </div>
          </div>
        </div>
        <div class="form-group">
          <label for="project">Email</label>
          <input type="text" id="emailId" name="emailId" class="form-control" formControlName="emailId">
          <div class="alert alert-danger" role="alert" *ngIf="!emailId.valid && (emailId.dirty || emailId.touched)">
            <div class="alert alert-danger" *ngIf="emailId.errors.required || emailId.errors.email">
              Email id is required, please enter a valid one
            </div>
            </div>
          </div>
        <div class="form-group">
          <label for="project">Project Status</label>
          <select name="projectStatus" id="projectStatus" class="form-control" formControlName="projectDetails">
            <option *ngFor="let status of projectStatus" [value]="status"> {{ status }}</option>
          </select>
        </div>
        <button class="btn btn-primary" type="submit" [disabled]="!contactForm.valid">Submit</button>
      </form>
      <br>
      <div class="container-fluid">
        <pre>{{ contactForm.value | json}}</pre>
      </div>
    </div>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode
  • projectname-validator.ts
import { FormControl } from "@angular/forms";
import { Observable } from "rxjs";

export class ProjectNameValidator {
    static invalidProjectName(control: FormControl): {[s:string]: boolean} {
        if (control.value === 'Test') {
            return {'invalidProjectName': true};
        }
        return null;
    }

    static asyncInvalidProjectName(control: FormControl): Promise<any> | Observable<any> {
        const promise = new Promise((resolve, reject) => {
            setTimeout(() => {
                if (control.value === 'test') {
                    resolve({'asyncInvalidProjectName': true});
                }
                else {
                    resolve(null);
                }
            }, 2000)
        })
        return promise;
    }
}
Enter fullscreen mode Exit fullscreen mode

Output

GitHub logo Rohithv07 / Extra-Material-For-Angular

Covering some features with more hands on

Extra-Material-For-Angular

Covering some features with more hands on

npm install --save-dev @angular-devkit/build-angular

npm install --save bootstrap@3

Data Binding

Directives

ngFor, ngIf, ngStyle, ngClass

Using renderer

Using HostListener

Using HostBinding

Building structural directive

Services

Logging Service and injecting

Data Service

Injecting Services into Services @Injectable()

Services for Cross - component communication

Routing

Setting and loading routes

Router Links

Navigation Paths and styling active router links

Passing parameters to Routes

Fetch Route parameters, also Reactively

Query paramaters, Fragments

Nested Routes

Redirecting and wildcards

Guards

>> canActivate
>> canActivateChild
>> Fake auth service and canDeactivate

Passing static data to route

Resolve Guard

Location startergies useHash: true

Observables

Undestanding angular observables

Custom observables

Data, Errors, Completion

Operators, Subject

Forms

Template Driven vs Reactive

Template Driven

Creating form

Accessing form with @ViewChild

Validation and validation error

ngModel with two way binding

Grouping form controls

Radio buttons

Resetting forms

Reactive Approach

Creating a form

Syncing HTML…

Discussion (0)