Skip to content

Angular Continues

Reactive Forms

For using reactive form you would need to inherit ReactiveFromsModule into your module.

So reactive forms give you more control over your forms so you end with handling or writing your own formcontrols.

In component you would need in import FormGroup and FormControl. Create /fetch a form in the component (here i defined myform) and for each element you need to define a minimum of key+formcontrol pair (check its definition).

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

@Component({
  selector: 'signup-form',
  templateUrl: './signup-form.component.html',
  styleUrls: ['./signup-form.component.css']
})
export class SignupFormComponent {
  myForm = new FormGroup({
    'usernamekey': new FormControl(),
    'passwordkey': new FormControl()
  })
}

next you would need to get that myform into the html in the form tag like ([formGroup] = “myForm”) and link your controls to the fields like (formControlName =”usernamekey”)

<form [formGroup]="myForm">
    <div class="form-group">
        <label for="username">Username</label>
        <input 
            formControlName ="usernamekey"
            id="username" 
            type="text" 
            class="form-control">
    </div>
    <div class="form-group">
        <label for="password">Password</label>
        <input 
            formControlName ="passwordkey"
            id="password" 
            type="text" 
            class="form-control">
    </div>
    <button class="btn btn-primary" type="submit">Sign Up</button>
</form>

Validations

In reactive forms we cant use html 5 validators instead we would be using the validator class so import it and in forms control refer it like below

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

@Component({
  selector: 'signup-form',
  templateUrl: './signup-form.component.html',
  styleUrls: ['./signup-form.component.css']
})
export class SignupFormComponent {
  myForm = new FormGroup({
    'usernamekey': new FormControl('usernameplaceholder', Validators.required),
    'passwordkey': new FormControl()
  })
}

Now in the html to add html based on validation use the myforms like below

<form [formGroup]="myForm">
    <div class="form-group">
        <label for="username">Username</label>
        <input 
            formControlName ="usernamekey"
            id="username" 
            type="text" 
            class="form-control">
            <div *ngIf="myForm.get('usernamekey').touched && myForm.get('usernamekey').invalid" class="alert alert-danger">Username is a required.</div>
    </div>
    <div class="form-group">
        <label for="password">Password</label>
        <input 
            formControlName ="passwordkey"
            id="password" 
            type="text" 
            class="form-control">
    </div>
    <button class="btn btn-primary" type="submit">Sign Up</button>
</form>

now minimizing the validation string we could use properties and refer them

//Add below in component
  get username(){
    return this.myForm.get('usernamekey');
  }

//in html
<div *ngIf="username.touched && username.invalid" class="alert alert-danger">Username is a required.</div>

Multiple Validator

//html
            <div *ngIf="username.touched && username.invalid" class="alert alert-danger">
                <div *ngIf="username.errors.minlength">Username should be minimum 5 characters.</div>
                <div *ngIf="username.errors.required">Username is a required.</div>
            </div>

  myForm = new FormGroup({
    'usernamekey': new FormControl('usernameplaceholder', 
        [Validators.required, Validators.minLength(5)]
        ),
    'passwordkey': new FormControl()
  });

Custom Validator

check validator in angular.io to get the interface of it and then create a class like below following the same.

import { AbstractControl, ValidationErrors } from '@angular/forms';

export class UsernameValidators{
    static cannotContainSpace(control:AbstractControl): ValidationErrors | null{
        if((control.value as string).indexOf(' ') >=0)
        {
            return { cannotContainSpace: true }
        }

        return null;
    }
}
  myForm = new FormGroup({
    'usernamekey': new FormControl('usernameplaceholder', 
        [Validators.required, Validators.minLength(5),
        UsernameValidators.cannotContainSpace]
        ),
    'passwordkey': new FormControl()
  });
            <div *ngIf="username.touched && username.invalid" class="alert alert-danger">
                <div *ngIf="username.errors.minlength">Username should be minimum 5 characters.</div>
                <div *ngIf="username.errors.required">Username is a required.</div>
                <div *ngIf="username.errors.cannotContainSpace">Username cannot contain spaces.</div>
            </div>

Async custom validators

must inherit from asyncvalidator. used mainly example: validating if username exists or not

import { AbstractControl, ValidationErrors } from '@angular/forms';

export class Uniquename {
    static shouldbeUnique(control: AbstractControl): Promise<ValidationErrors | null> {

        return new Promise((resolve, reject) => {
            setTimeout(() => {
                if (control.value === "tejaswi")
                    resolve({ shouldbeunique: true });
                else
                    resolve(null);
            }, 2000);
        });
    }
}
  myForm = new FormGroup({
    'usernamekey': new FormControl('usernameplaceholder', 
        [Validators.required, Validators.minLength(5),
        UsernameValidators.cannotContainSpace],
        Uniquename.shouldbeUnique
        ),
    'passwordkey': new FormControl()
  });
            <div *ngIf="username.touched && username.invalid" class="alert alert-danger">
                <div *ngIf="username.errors.minlength">Username should be minimum 5 characters.</div>
                <div *ngIf="username.errors.required">Username is a required.</div>
                <div *ngIf="username.errors.cannotContainSpace">Username cannot contain spaces.</div>
                <div *ngIf="username.errors.shouldbeUnique">Username should be unique.</div>
            </div>
  myForm = new FormGroup({
    'usernamekey': new FormControl('usernameplaceholder', 
        [Validators.required, Validators.minLength(5),
        UsernameValidators.cannotContainSpace],
        Uniquename.shouldbeUnique
        ),
    'passwordkey': new FormControl()
  });

Debugging the reactive forms

  get username(){
    return this.myForm.get('usernamekey');
  }

  log(x){
    console.log(x);
  }

        <input 
            formControlName ="usernamekey"
            (change) ="log(username)"
            id="username" 
            type="text" 
            class="form-control">

Loader Image: Will work with async

<div *ngIf="username.pending"> Checking for uniqueness...</div>

similar to formControlName we ahave formGroupName which is used for complex multi level forms.

FormArray:

sometimes you want a input field in which user can enter multiple values (array) and submit it. For it we use formarray

import { Component, OnInit } from '@angular/core';
import { FormArray, FormControl, FormGroup } from '@angular/forms';

@Component({
  selector: 'app-newcourseform',
  templateUrl: './newcourseform.component.html',
  styleUrls: ['./newcourseform.component.css']
})
export class NewcourseformComponent {
  myForm = new FormGroup({
    topics: new FormArray([])
  });

  addTopic(topic: HTMLInputElement){
    this.Topics.push(new FormControl(topic.value));
    topic.value='';
  }

  get Topics(){
    return (this.myForm.get('topics') as FormArray);
  }

  remove(topic: FormControl){
    let index =this.Topics.controls.indexOf(topic);
    this.Topics.removeAt(index);
  }
}
<form >
    <input type="text" class="formcontrol"
    (keyup.enter)="addTopic(topic)" #topic>
    <ul class="list-group">
        <li *ngFor="let topic of Topics.controls"
        (click)="remove(topic)" class="list-group-item">{{topic.value}}</li>
    </ul>
</form>

Form Builder

2 ways of form building

export class NewcourseformComponent {
  form;
  myForm = new FormGroup({
    name: new FormControl(),
    contact: new FormGroup({
      email: new FormControl(),
      phone: new FormControl()
    }),
    topics: new FormArray([])
  });

  constructor(fb:FormBuilder){
    this.form = fb.group({
      name: ['', Validators.required],
      contact: fb.group({
        email:[],
        phone: []
      }),
      topic: fb.array([])
    })
  }
}

Working With Http

To start consuming HTTP requests first you need to import HttpClientModule in your module.

Once imported let’s start with getting the data. for it, we would need httpClient which has the get method like below

import { HttpClient } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';

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

  posts:any[];

  constructor(http: HttpClient){
    http.get('https://jsonplaceholder.typicode.com/posts')
    .subscribe(response =>{
      console.log(response);
    });
    
  }
}

Now let’s store the data into a posts variable also instead of response we now are defining the type of response we are getting this is because subscriber is strongly typed.

export class PostsComponent {

  posts:any[];

  constructor(http: HttpClient){
    http.get('https://jsonplaceholder.typicode.com/posts')
    .subscribe((response :any[]) =>{
      this.posts =response;
    });
  }
}

<ul class="list-group">
    <li *ngFor="let post of posts" class="list-group-item">
        {{ post.title }}
    </li>
</ul>

Posting Data:

Now lets look at hte ways for posting the data

<input (keyup.enter)="createPost(title)" #title type="text" class="form-control">

//<any> means that the response we get here is of type any so we dont type check the response
  createPost(input: HTMLInputElement){
    let post ={ title: input.value };
    input.value ='';
    this.http.post<any>(this.url, post).subscribe(response =>{
      post['id'] = response.id;
      this.posts.unshift(post);
      console.log(response);
    })

update data

<button (click)='updatePost(post)' class="bt btn-default btn-sm">Update</button>

  updatePost(post){
    this.http.put(this.url + post.id,post).subscribe(response =>{
      console.log(response);
    })
  }

delete posts

<button (click)='deletePost(post)' class="bt btn-default btn-sm">Delete</button>
  deletePost(post){
    this.http.delete(this.url + post.id).subscribe(response =>{
      let index = this.posts.indexOf(post);
      this.posts.splice(index,1);
    });
  }

LifeCycle Hooks

ngOnInitwhen a component gets loaded first to be executed

Published inUncategorised

Be First to Comment

Leave a Reply

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