Angular Change Detection

Change Detection means updating the DOM whenever data is changed. Angular provides two strategies for Change Detection.

Change Detection: The process of updating the view (DOM) when the data has changed

Angular ng-template, ng-container , ngTemplateOutlet

1- <ng-template> is a template element that Angular uses with structural directives like *ngIf, *ngFor, [ngSwitch] and custom directives
Note: the ng-template directive represents an Angular template

2- <ng-container> We can avoid having to create that extra div, we can instead use ng-container directive

<ng-container *ngFor="let item of items">
   <p *ngIf="item.id">{{item.name}}</p>
</ng-container>

3- *ngTemplateOutlet
We can used as a container to templates that can be reused at multiple places.

Angular Routing: router outlet

<router-outlet></router-outlet>
Where we want to output to display for a route, we can configure using router outlet
by default, angular has one router outlet in app.html

Route Information’s
1-Routing Strategy
2-Base href
3-Router module
4-Router outlet
5-Configuring Router
6-Parameterized Routes
7-Router link
8-Redirecting Routes
9-Wildcard Routes
10-Query params in Routes
11-Child Routes
12-Route Guards

Angular ChangeDetectorRef

import { JsonPipe } from '@angular/common';
import { Component, VERSION, ViewChild, AfterViewInit , AfterViewChecked, AfterContentChecked, SimpleChanges ,OnChanges, ElementRef  } from '@angular/core';
import { ChildComponent } from './child/child.component';
import { ChangeDetectorRef } from '@angular/core';
@Component({  
   selector: 'my-app',  templateUrl: './app.component.html',  
   styleUrls: [ './app.component.css' ]
})
export class AppComponent implements AfterViewInit, AfterViewChecked {  
constructor(private cdRef:ChangeDetectorRef) {}  
@ViewChild(ChildComponent) hello:ChildComponent;  
@ViewChild('title') title: ElementRef;  
aname = 'Ajay' 
 name = 'Angular ' + VERSION.major; 
 xx:any;  
ngAfterViewInit() {   
   this.aname = this.hello.name  
}  
ngAfterViewChecked(){    
   this.aname = this.hello.name   
   //console.log(this.title.nativeElement.innerText)    
   this.cdRef.detectChanges();  
} 
ngAfterContentInit(){    
   console.log("after content init");   
   // this.aname = this.hello && this.hello.name  
}  
ngOnChanges(changes: SimpleChanges) {    
   console.log(changes)       
   this.xx = changes 
 }
}

@viewChild Angular

Property decorator that configures a view query
View queries are set before the ngAfterViewInit callback is called.

import { Component, OnInit,AfterViewInit,  viewChild } from '@angular/core';

@Component({
  selector: 'app-example',
  templateUrl: './example.component.html',
  styleUrls: ['./example.component.css']
})
export class ExampleComponent implements OnInit, AfterViewInit {

  constructor() { }
  @ViewChild('addBtn') addBtn:ElementRef;
  ngOnInit(): void {
  }
   ngAfterViewInit() {
    // child is set
    console.log(this.addBtn.nativeElement)
  }

}

<button #addBtn>add</button>

…………………………………………………………………………………………………………………………………….

@viewchildren

@viewchildren decorator returns the list of different native DOM elements through og QueryList
@ViewChild() in a component can communicate with another component or a directive.
But if we want to access multiple child references, then we have to use @ViewChildren.

import {AfterViewInit, ElementRef, viewChildren,QueryList} from '@angular/core'
export class AppComponent implements AfterViewInit {
// Accessing multiple native DOM elements using QueryList
  @ViewChildren(HelloComponent) myValue: QueryList<HelloComponent>;
  ngAfterViewInit() {
     console.log("Hello ", this.myValue.toArray(););
  }
}
<hello name="{{ name }}"></hello>

<hello name="{{ name }}"></hello>

<hello name="{{ name }}"></hello>

Angular PreloadingStrategy

app-routing.module.ts
 import { PreloadAllModules } from '@angular/router';
 @NgModule({ 
 imports: [
   RouterModule.forRoot(routes, { useHash: false, 
   onSameUrlNavigation: 'reload', 
   preloadingStrategy: PreloadAllModules })
  ],    
 exports: [RouterModule]  
})

.

Custom Preloading Strategy

app-routing.module.ts
import {CustomPreloadingStrategy} from './customPreloadingStrategy';
 import { PreloadAllModules } from '@angular/router';
 @NgModule({ 
 imports: [
   RouterModule.forRoot(routes, { useHash: false, 
   onSameUrlNavigation: 'reload', 
   preloadingStrategy: CustomPreloadingStrategy })
  ],    
 exports: [RouterModule]  
})
///////////////////////////////////////
{ path: 'dashboard', 
    loadChildren: () => import('./dashboard/dashboard.module').then(m => m.DashboardModule),
    data: { preload: true, delay:10000 
}

app.module.ts
import {CustomPreloadingStrategy} from './customPreloadingStrategy';
@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
  ],
  providers: [CustomPreloadingStrategy],
  bootstrap: [AppComponent]
})

customPreloadingStrategy.ts -- service
import {Injectable} from '@angular/core';
import { PreloadingStrategy, Route } from '@angular/router';
import { Observable, of, timer  } from 'rxjs';
import { flatMap } from 'rxjs/operators';

@Injectable()
export class CustomPreloadingStrategy implements PreloadingStrategy {
    preload(route: Route, loadMe: () => Observable<any>): Observable<any> {
    
        if (route.data && route.data['preload']) {
          var delay:number=route.data['delay']
          console.log('preload called on '+route.path+' delay is '+delay);
          return timer(delay).pipe(
            flatMap( _ => { 
              console.log("Loading now "+ route.path);
              return loadMe() ;
            }));
        } else {
          console.log('no preload for the path '+ route.path);
          return of(null);
        }
      }
}


Angular Guards

What are Route Guards?

Angular’s route guards are interfaces that can tell the router whether or not it should allow navigation to a requested route. They make this decision by looking for a true or false the return value from a class that implements the given guard interface.

There are five different types of guards and each of them is called in a particular sequence. The router’s behavior is modified differently depending on which guard is used. The guards are:

There are five different types of guards and each of them is called in a particular sequence. The router’s behavior is modified differently depending on which guard is used. The guards are:

  • CanActivate
  • CanActivateChild
  • CanDeactivate
  • CanLoad
  • Resolve
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http'
import { Router } from '@angular/router'
@Injectable()
   export class AuthService {
      constructor(
          private http: HttpClient,
          private _router: Router
         ) { }
       loggedIn() {
          return !!localStorage.getItem('token')
     }
}
CanActivate
import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';
import { AuthService } from './auth.service';

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(private _authService: AuthService,
    private _router: Router) { }

  canActivate(): boolean {
    if (this._authService.loggedIn()) {
      console.log('true')
      return true
    } else {
      console.log('false')            
      this._router.navigate(['/login'])
      return false
    }
  }
}

Angular routing- LazyLoad

In a single-page app, you change what the user sees by showing or hiding portions of the display that correspond to particular components, rather than going out to the server to get a new page. As users perform application tasks, they need to move between the different views that you have defined. To implement this kind of navigation within the single page of your app, you use the Angular Router.

Note: Routing helps you to define the navigations for your applications, so if you want to move one screen to another screen that no loading and refreshing the page

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { HomeComponent } from '@app/home/home.component';
import { AuthGuard } from './guards/auth.gards';
const routes: Routes = [
{ path: 'home', component: HomeComponent, canActivate:[AuthGuard]},
{
  path: 'contact',
  loadChildren: './contact/contact.module#ContactModule',
  canActivate: [AuthGuard, CheckContactAddressGuard]
},
{
path: 'login',
loadChildren: './login/login.module#LoginModule'
},
{ path: 'unauthorized',component:UnauthorizedAccessComponent, canActivate:[AuthGuard]},
{ path:'**', redirectTo: '/home', pathMatch: 'full' },
];
@NgModule({
imports: [RouterModule.forRoot(routes,{useHash:true, onSameUrlNavigation:'reload'})],
exports: [RouterModule]
})
export class AppRoutingModule {
}

Angular setValue, patchValue

Angular setValue
Sets the value of the Form Group. It accepts an object that matches the structure of the group, with control names as keys.

Set the complete value for the form group
const form = new FormGroup({
  first: new FormControl(),
  last: new FormControl()
});
console.log(form.value); // {first: null, last: null}
form.setValue({first: 'Nancy', last: 'Drew'});
console.log(form.value); // {first: 'Nancy', last: 'Drew'}
Continue reading “Angular setValue, patchValue”

Angular Reactive form Validations

Validating input in reactive forms

Validator functions
Validator functions can be either synchronous or asynchronous.

Sync validators: Synchronous functions that take a control instance and immediately return either a set of validation errors or null. You can pass these in as the second argument when you instantiate a FormControl.

Async validators: Asynchronous functions that take a control instance and return a Promise or Observable that later emits a set of validation errors or null. You can pass these in as the third argument when you instantiate a FormControl.

Continue reading “Angular Reactive form Validations”