Total Pageviews

Saturday 12 October 2019

Reactive forms in Angular

Reactive forms:

Reactive forms are made up of HTML and RxJs to maintain its state. As the name suggests it listen to changes in its values and reacts accordingly with validation such as it will throw errors, give feedback, perform database operations, etc. according to the action performed.

Reactive forms were introduced in Angular 2.

Upside of Reactive Forms:

1) Form input controls can be added dynamically very easily.

2) Run time validations.

3) Easy to unit test as all codes are in the component class.

4) It's different than template-driven forms where the

Downside:

1) Need to write too many codes.

How to use:

1) import FormsModule and ReactiveFormsModule in the application module i.e. (in src/app/app.module.ts)

2) In component class add FormBuilder, FormGroup, Validators symbols that are used to create Angular reactive forms

3) In our component’s ngOnInit() life-cycle event, we will create the form as below:

ngOnInit() {
    this.bookingForm = this.userFormBuilder.group({
                u_name: ["", [Validators.required, Validators.pattern('^[a-zA-Z ]*$')]],
                u_email: ["", [Validators.required, Validators.pattern('^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$')]],
                u_phone: ["", [Validators.required, Validators.pattern('[1-9]{1}[0-9]{9}')]],
                u_seats: ["", Validators.required],
                atteName: this.userFormBuilder.array([]),
    });
}

4) Add a get property to make easy to access the form controls on the HTML form:

5) get formControls() { return this. bookingForm.controls; }

6) Add the submitLogin() method:

submitLogin() {    
    if (this.bookingForm.invalid) { 
         return;
     }else{
      console.log("Form data ", JSON.stringify(this.bookingForm.value));
      this.submitted = true;      
     }
 }

HTML form

<div class="row">

<div class="col-12 col-sm-12 col-md-12">

<form [formGroup]="bookingForm" novalidate class="mt-1" (ngSubmit)="submitLogin()">

<fieldset class="form-group">

<div>

<label>Name</label>

<input type="text" class="form-control" pattern="^[A-Za-z ]+$" formControlName="u_name" required>

</div>

<div *ngIf="bookingForm.controls['u_name'].invalid && (bookingForm.controls['u_name'].dirty || bookingForm.controls['u_name'].touched)" class="alert alert-danger">

<div *ngIf="bookingForm.controls['u_name'].errors.required">

Please enter your name

</div>

<div *ngIf="bookingForm.controls['u_name'].errors.pattern">

Only letters and spaces are allowed

</div>

</div>

</fieldset>

<fieldset class="form-group">

<div>

<label>Email</label>

<input type="email" class="form-control" formControlName="u_email" required>

</div>

<div *ngIf="bookingForm.controls['u_email'].invalid && (bookingForm.controls['u_email'].dirty || bookingForm.controls['u_email'].touched)" class="alert alert-danger">

<div *ngIf="bookingForm.controls['u_email'].errors.required">

Please enter your email

</div>

<div *ngIf="bookingForm.controls['u_email'].errors.pattern">

Invalid email

</div>

</div>

</fieldset>

<fieldset class="form-group">

<div>

<label>Phone Number</label>

<input type="number" class="form-control" formControlName="u_phone">

</div>

<div *ngIf="bookingForm.controls['u_phone'].invalid && (bookingForm.controls['u_phone'].dirty || bookingForm.controls['u_phone'].touched)" class="alert alert-danger">

<div *ngIf="bookingForm.controls['u_phone'].errors.pattern || bookingForm.controls['u_phone'].errors.required">

Please enter 10 digit phone number

</div>

</div>

</fieldset>

<fieldset class="form-group">

<div>

<label>No. of Seats</label>

<select class="form-control" formControlName="u_seats" (change)="onSeatSelected($event.target.value)">

<option [selected] value="" disabled>Please select number of seats </option>

<option [value]="seatIdx" *ngFor="let seatIdx of seats">{{ seatIdx }}</option>

</select>

</div>

<div *ngIf="bookingForm.controls['u_seats'].invalid && (bookingForm.controls['u_seats'].dirty || bookingForm.controls['u_seats'].touched)" class="alert alert-danger">

<div *ngIf="bookingForm.controls['u_seats'].errors.required">

Please enter number of seats

</div>

</div>

<div *ngIf="notAvailableSeat" class="alert alert-danger">

Number of seats selected is more than available seats

</div>

</fieldset>

<fieldset class="form-group" >

<div formArrayName="atteName" *ngFor="let attName of bookingForm.controls.atteName['controls']; let i = index">

<ng-container [formGroupName]="i">

<label>Name of Attendee {{i + 1}}</label>

<input formControlName="attName" type="text" class="form-control" required>

<div *ngIf="(bookingForm.controls.atteName['controls'].length > 1) && (getValidity(i) && isValidFormSubmitted) || attName.invalid && (attName.dirty || attName.touched)" class="alert alert-danger">

Please enter the name of Attendee {{i + 1}}

</div>

</ng-container>

</div>

</fieldset>

<div class="form-group float-right">

<button type="submit" class="btn btn-primary" [disabled]="submitted">Submit</button>

<button type="button" class="btn btn-primary ml-2" (click)="backToBookingListScreen()" [disabled]="submitted">Cancel</button>

</div>

</form>

</div>

</div>

I have created much complex form and had added custom validations, to get into more details visit

https://github.com/swati61/Event-Booking-Application








Wednesday 25 September 2019

JavaScript : Copy an object property into another



The easiest way to copy object properties on to another is Object.assign()


Example:
function obj1(){
let target = { a: 1, b: 2 };
return target;
}

function obj2(){
let source = { b: 4, c: 5 };
let new_source = Object.assign(obj1(), source);
new_source.d = "Hello";   //add a new property
console.log(new_source);    //Output : Object { a: 1, b: 4, c: 5, d: " Hello" }
}





Friday 30 August 2019

JavaScript Interview Question | Closure

In many interview question nowdays there is a popular interview question based on JavaScript closure and that is:


Input:    messageWord(‘2’)(‘3’)(‘4’)

Output: ‘234’

Solution:

function messageWord (x){
  return function(y){
      return function(z){
        return x + y + z;
      };
  };
}

JavaScript Closure


JavaScript Closure: A closure is the combination of a function (inner function) which have access to the parent scope (outside function variable).            

Advantages of closure:

1)      In the object-oriented programming paradigm, encapsulation is one of the key features. Encapsulation hides the inner work of an object from the outside world. But as JavaScript is a scripting language it doesn’t have encapsulation feature.

Here Closure comes in a picture, with the help of “Closure” we can access the parent function variable and arguments.
2)      Example:

var myFun = (function () {
    var privateFun = function () {
        alert(' privateFun ');
    }

    return {
        publicFun : function () {
            privateFun();
        }
    }
})();

In this example, I can access the publicFun but not privateFun.
3)      Closures are helpful in APIs callback functions requirement.

There are many examples available for closure, if you want to explore more.


Monday 24 June 2019

Preloading in Angular 7


When user navigates to the lazy loadable section of the application then the router has to fetch the required module from the server which can take time. In this case Preloading is a very helpful concept, in this router downloads or preloads the lazy loadable module asynchronously in background.

This speed up the load time of angular applications.

Preloading can be done in 4 steps;

1.    Initial Load where all the necessary components load to bootstrap the application.
2.    Bootstrap where application initializes with required modules.
3.    Preloading, in this router, preloads modules in background while app is running and user interacts with the application.
4.    Now once the preloading is done user clicks on lazy loadable module where navigation is instant and fast.

To enable preload, we can pass a preloading strategy into forRoot. Angular provides two inbuilt strategies –
  • NoPreloading— This is default behavior i.e. no module will be preloaded.
  • PreloadAllModules — All modules will be preloaded as fast as possible.
In PreloadAllModules, we can start by adding a data object to the route’s config:

import { NgModule } from '@angular/core';
import { RoutesRouterModulePreloadingStrategy } from '@angular/router';

import { LoginComponent } from './login/login.component';
import { HomeComponent } from './home/home.component';
import { RegisterComponent } from './register/register.component';
import { CustomPreloadingStrategy } from './register/custom-preloading-strategy';

const routesRoutes = [{
    path: "",
    redirectTo: "/login",
    pathMatch: 'full'
  },
    {
        path: 'login',
        component: LoginComponent
    },
    {
        path: 'home',
        component: HomeComponent
    },
    {
        path: 'register',
        loadChildren: "./register/register.module#RegisterModule",
        data:{preload:true}
    }
];

@NgModule({
  imports: [RouterModule.forRoot(routes, { preloadingStrategy : CustomPreloadingStrategy } )],
  exports: [RouterModule],
  providers: [CustomPreloadingStrategy]
})
export class AppRoutingModule { }


this data object has two boolean properties:

·         preload — To preload module or not
·         delay — To preload module with some delay

Now we will create CustomPreloadingStrategy class, in which there is a preload method which takes two parameters: a route and the function that actually does the preloading. In it we check if the preload property is set to true. And if it is true then we will call the load function.

import { Observableofobservable } from 'rxjs';
import { PreloadingStrategyRoute } from '@angular/router';
import { Injectable } from '@angular/core';

@Injectable()
export class CustomPreloadingStrategy implements PreloadingStrategy {
    preload(routeRouteload: () => Observable<any>): Observable<any> {
   
        if (route.data && route.data['preload']) {
          console.log('preload called');
          return load();
       } else {
          console.log('no preload');
          return of(null);
        }
      }
    
}


The first parameter is the active Route. We use this to extract the information about the route, which is being loaded.

The second parameter is Observable function, which we need to return if we want to preload this module. We can return Observable of null, if we do not want to preload the module.

Finally, we need to enable the strategy by passing it to the provider and to RouterModule.forRoot.

@NgModule({
  imports: [RouterModule.forRoot(routes, { preloadingStrategy : CustomPreloadingStrategy } )],
  exports: [RouterModule],
  providers: [CustomPreloadingStrategy]
})
export class AppRoutingModule { }





Thursday 20 June 2019

Angular 7 | Can't bind to 'formGroup' since it isn't a known property of 'form'


If there are multiple module files in application then only adding ReactiveFormsModule in app.module.ts is not enough.



import { FormsModule, ReactiveFormsModule } from '@angular/forms';`

@NgModule({
  declarations: [
    AppComponent,
  ]
  imports: [
    FormsModule,
    ReactiveFormsModule,
    RegisterComponent,
],
...



This will not work, when I use a [formGroup] directive from a component added in another module, e.g. using [formGroup] in register.component.ts which is subscribed in register.module.ts file:

import { NgModule }       from '@angular/core';
import { CommonModule }   from '@angular/common';
import { RegisterComponent } from './author.component';

@NgModule({
  imports: [
    CommonModule,
  ],
  declarations: [
    RegisterComponent,
  ],
  providers: [...]
})
export class RegisterModule {}



By default ReactiveFormsModule would be inherited by all its children modules like register.module but this is not true in this case. We need to import ReactiveFormsModule in register.module.ts in order to make all directives to work:



import { FormsModule, ReactiveFormsModule } from '@angular/forms';
...

@NgModule({
  imports: [
    ...,
    FormsModule,    //added here too
    ReactiveFormsModule //added here too
  ],
  declarations: [...],
  providers: [...]
})
export class RegisterModule {}



So, the conclusion is if there are submodules in application, then make sure to import ReactiveFormsModule in each submodule file.

Wednesday 19 June 2019

Lazy Loading in Angular 7


By default, NgModules are eagerly loaded i.e. as soon as app loads, so do all the NgModules. But for large apps with many routes, lazy loading is very helpful.

Lazy loading loads the components asynchronously when a specific route is activated or when required. It helps to increase the performance and speed of the application. It splits the app into multiple bundles.

Lazy loading was implemented in the Angular router (@angular/router) to fix this. 

Feature module is that module which you want to download when required.

Below is the step by step example of lazy loading:

1) Create a new project with routing option

ng new my-app –routing

2) Create two components - login and register

ng generate component login
ng generate component register

3) Create respective module files in each component folder     as below:

register.module.ts

4) Create a respective router module file in each component folder

register-routing.module.ts

Now my project structure will look like below:


5) Import router module in app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';


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


Remove register component import and declaration from app.module.ts, as each view will have their own module defined.


6) Add code in component routing

my-app-routing.module.ts

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { RegisterComponent } from './register.component';

import { FormsModule, ReactiveFormsModule } from '@angular/forms';

const routes: Routes = [
  {
    path: '',
    component: RegisterComponent
  }];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class RegisterRoutingModule { }



By using forChild we will call child modules (featured module) in app’s main routing module.

In my-app.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

import { RegisterRoutingModule } from './register-routing.module';
import { RegisterComponent } from './register.component';

import { ReactiveFormsModule } from '@angular/forms';

@NgModule({
  declarations: [RegisterComponent],
  imports: [
    CommonModule,
    ReactiveFormsModule,
    RegisterRoutingModule
  ]
})
export class RegisterModule { }


Then in app’s main routing module we will define Routes using loadChildren attribute. The loadChildren module uses # to define each independent module’s name.


In app-routing.module.ts

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

import { LoginComponent } from './login/login.component';
import { RegisterComponent } from './register/register.component';

const routes: Routes = [{
    path: "",
    redirectTo: "/login",
    pathMatch: 'full'
  },
    {
        path: 'login',
        component: LoginComponent
    },
    {
        path: 'register',
        loadChildren: './register/register.module#RegisterModule'
    }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }


And finally add links to Route/Open views

register.component.html

<button [disabled]="loading" class="btn btn-primary" routerLink="register">Register</button>


Now run application using by using below command:

ng-serve

Which will produce below output.



At first only login module will load see attached screenshot



After clicking on register button, register module will load.


Hope this helps. 







Microsoft Logo using flexbox and Reactjs

 <!DOCTYPE html> <html> <head>     <script src="https://unpkg.com/react@18/umd/react.development.js" crossori...