Tuesday, October 25, 2022

Angular tutorial part 5 : Learn Angular Routing and testing

 

Routing and
testing

Routing in Angular

•      Component Router

•      Navigating Routes

•      Route Parameters

•      Query Parameters

•      Child Routes

Implement routes first in app routing module

•       Basically this helps creating menus to help user navigate to various components and pass parameters to components.

•       There are various ways routes can be implemented.

•       One of the best ways => In application Routing module import the route dependencies import { Routes, RouterModule ,ActivatedRoute } from '@angular/router';

•        Routes take 2 params,the path name and the target component,all the app routes can be defined here

•       const routes: Routes = [{path: 'Main', component:AppComponent}, {path: 'Form', component: FormappComponent},];

•      Pass this routes to the NGModule imports

•      @NgModule({

•        imports: [RouterModule.forRoot(routes)],

•        exports: [RouterModule]

•      })

•     To create a default routing module when component is created ,use the cli command

•     ng g m [ModuleName] --routing

 

 

Create a new Menu component

•       Generate a new component within the app called menu

•       Add the menu links

•       Welcome To Menu

•         <nav> <a class="button" routerLink="Main">Main</a> | 

•           <a class="button" [routerLink]="['Form',{value1: 'bar'}]">USerForm1</a> </nav>  

•         <router-outlet></router-outlet>

•       Router link param takes two params to genereate hyperlink 1. routename defined in route,then param if needed to be sent to second component.

•       Redirect the application now to point to this menu component as entry point,to do that

•       Change the bootstrap in the appmodule to menucomponent

 

•      bootstrap: [MenuComponent ] 

•     Now when the application starts you will see the 2 menu links ->main and form,each pointing to the component we have created earlier and defined in the routes

•    

 

Passing and Reading params

•       Routerlink can take route and params as inputs,the following router link redirects to form component and sends a param value1 .

•           <a class="button" [routerLink]="['Form',{value1: 'bar'}]">USerForm1</a> </nav>  

•       To Read the param in the target component,we will use activatedroute module

•       import { Router,ActivatedRoute } from '@angular/router'; and inject

•       In component constructor only   constructor(private _Activatedroute:ActivatedRoute,) { }

 

•       And in the  components of form,we will read the params,using activatedroute,parammap and an observable.

•       this._Activatedroute.paramMap.subscribe(params => { 

•           console.log(params);

•           console.log(params.get('value1'));//params passed to this component by routing

•      

 

 

 

 

Component Router

•       • Use the router-outlet directive to tell Angular where you

•       want a route to put its template <router-outlet></

•       router-outlet>

 

Adding the routeconfig to component or module

•       @RouteConfig([

•        {path: '/home', name: 'Home', component: HomeComponent, useAsDefault: true},

•        {path: '/about', name: 'About', component: AboutComponent},

•        {path: '/experiments', name: 'Experiments', component: ExperimentsComponent}

•       ])

•       export class AppComponent {}

 

•       <div id="container">

•        <router-outlet></router-outlet>

•       </div>

 

Navigating Routes

•       Add a routerLink attribute directive to an anchor tag

• Bind it to a template expression that returns an array of route link parameters Users

 • Navigate imperatively by importing Router, injecting it, and then calling .navigate() from within a component method

• We pass the same array of parameters as we would to the routerLink directive this._router.navigate( ['Users'] );

•     <div id="menu">

•      <a [routerLink]="['/Home']" class="btn">Home</a>

•      <a [routerLink]="['/About']" class="btn">About</a>

•      <a [routerLink]="['/Experiments']" class="btn">Experiments</a>

•     </div>

Routerlink

•       Add a routerLink attribute directive to an anchor tag

• Bind it to a template expression that returns an array of route link parameters Users

 • Navigate imperatively by importing Router, injecting it, and then calling .navigate() from within a component method

• We pass the same array of parameters as we would to the routerLink directive this._router.navigate( ['Users'] );

•         Programmatically allows you to navigate to path

export class App {

constructor(private _router: Router) {}

navigate(route) { this._router.navigate([`/${route}`]); }

 }

Query Parameters

• Denotes an optional value for a particular route

• Do not add query parameters to the route definition

•     { path:'/users', name: UserDetail, component:

•     UserDetail }

• Add as a parameter to the routerLink template

•     expression just like router params: <a

•     [routerLink]="['Users', {id: 7}]"> {{user.name}} </a>

• Also accessed by injecting RouteParams into a component

Query Params

•        <div>

•         <button [routerLink]="['./MyComponent', {id: 1}]">

•         My Component Link</button>

•         <button [routerLink]="['./AnotherComponent', {queryParam: 'bar'}]">

•         Another Component Link</button>

•        </div>

•        Com

Query Params

•     import { Component } from 'angular2/core';

•     import { RouteParams } from 'angular2/router';

•     @Component({

•      selector: 'my-component',

•      template: `<h1>my component ({{routeParams.get('id')}})!</h1>`

•     })

•     export class MyComponent {

•      constructor(routeParams: RouteParams) {

•      this.routeParams = routeParams;

•      }

•     }

Child Routes

• Ideal for creating reusable components

• Components with child routes are “ignorant” of the parents’ route implementation

• In the parent route config, end the path with /…

• In the child config, set the path relative to the parent path

• If more than one child route, make sure to set the default route

Child Routes

•       @RouteConfig([ {

•        path:'/another-component/...',

•        name: 'AnotherComponent',

•        component: AnotherComponent }

•       ])

•       export class App {}@RouteConfig([

•        {

•        path:'/first', name: 'FirstChild',

•        component: FirstSubComponent }])

•       export class AnotherComponent {}

Testing

•     Testing is good practise and mandatory in any project.

•     Testing helps remove bugs and also check the functionality of your application.

•     Angular wraps Jasmine methods

•      Import all necessary Jasmine methods from angular11/

•     testing

•      Import the classes to test

•      Include providers by importing beforeEachProviders

•     and then calling it with a method that return

 

 

•     TestBed is the primary api for writing unit tests for Angular applications and libraries.

•     Methods

•     compileComponents()

•     inject()

•     get()

•     execute()

•     overrideModule()

•     overrideComponent()

•     overrideDirective()

•     overridePipe()

•     overrideProvider()

•     overrideTemplateUsingTestingModule()

•     createComponent()

 

Testing a component

•        Create a component with title =I love  pizza

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

•        @Component({

•          selector: 'app-pizza',  templateUrl: './pizza.component.html', styleUrls: ['./pizza.component.css']

•        })export class PizzaComponent implements OnInit {

•          title = "I love pizza!"  constructor() { }  ngOnInit() {  }}

 

•        We will create a test to see that component is create with title “I love pizza”

Testing a component (contd..)

•       Writing tests in Angular is easy, now we are going to write a simple test within the describe() function.

•       it(`should have a title 'I love pizza!'`, async(() => { //test has to be written within it

•         fixture = TestBed.createComponent(PizzaComponent);  //create an instance of the component using testbesd class

•         component = fixture.debugElement.componentInstance; //once the component is rendered

•         expect(component.title).toEqual('I love pizza!');//check for whether the component title is equal to “I love pizza”

•       //expect asserts or compares values to expected values

•       }));

•       Run ng test

•       To specifically test one test spect only  ->ng test --main ./src/app/app.component.spec.ts

Testing services

•       To test a service, you set the providers metadata property with an array of the services that you'll test or mock.

•       let service: MyserviceService;

•       beforeEach(() => {  TestBed.configureTestingModule({ providers: [MyserviceService

•       ] });});

•       Then inject it inside a test by calling TestBed.inject() with the service class as the argument.

•       it('should use ValueService', () => { service = TestBed.inject(MyserviceService

•       ); expect(service.showTodayDate()).toBe('real value'); });

 

Angular tutorial part 4 - Learn Angular The HTTP Module •Methods • Observable.toPromise • Error Handling • Header Pipes

 

Server communication

• The HTTP Module

•Methods

• Observable.toPromise

• Error Handling

• Header

Pipes

 

Http Module

•     Http module basically is used to connect to resource on the network

•     and process the result.

•     Returns an observable

Http module

•     request: performs any type of http request

•     get: performs a request with GET http method

•     post: performs a request with POST http method

•     put: performs a request with PUT http method

•     delete: performs a request with DELETE http method

•     patch: performs a request with PATCH http method

•     head: performs a request with HEAD http method

To use http in component

•       Import httpmodule in app module

•       import { HttpClientModule } from '@angular/common/http';

•       Add to imports , imports: [       HttpClientModule   ], in app module

•       Import the following in component ts

•       import { HttpClient, HttpHeaders,HttpHeaderResponse } from "@angular/common/http";

•       Inject httpclient in constructor: constructor(private http: HttpClient) { }

 

 

 

 

Making http post call

•     Real time code creates user record in mysql via springboot endpoint,angular basically calls this springboot endpoint and passes and user class object.

•      

•     private url = 'http://127.0.0.1:8080/insertuser'; 

•     CreateUser(user: User): Observable<any>{

•       var httpOptions = {

•         headers: new HttpHeaders({ 'Content-Type': 'application/json'})

•       };

•       console.log('value from service'+JSON.stringify(user));

•       return this.http.post<User>(this.url,user,httpOptions);

•    

 

Walk through sample code

•     loadItems() {

•     return this.http.get(BASE_URL) //basically a get call is made using the http module

•     .map(res => res.json())/returns a json respononse

•     .toPromise();

•     }

•     createItem(item: Item) {

•     return this.http.post(`${BASE_URL}`, JSON.stringify(item), HEADER)

•     //basically a post call is made on the http module

•     .map(res => res.json()) //process the json response

•     .toPromise();

•     }

Http Put and Delete

•     updateItem(item: Item) {

•     return this.http.put(`${BASE_URL}${item.id}`,

•     JSON.stringify(item), HEADER)

•     .map(res => res.json())

•     .toPromise();

•     }

•     deleteItem(item: Item) {

•     return this.http.delete(`${BASE_URL}${item.id}`)

•     .map(res => res.json())

•     .toPromise();

•     }

Using Observable

•      Observables are really just functions that throw values

•     . Objects called observers define callback functions for next(), error(), and complete().• Composed of subjects and observers

• A subject performs some logic and notifies the

•     observer at the appropriate times

•     Observable.subscribe is used to check result of the method

•     We finalize an observable stream by subscribing to it

•     The subscribe method accepts three event handlers

•     onNext is called when new data arrives

•     onError is called when an error is thrown

•     onComplete is called when the stream is completed

•     source.subscribe(

•     x => console.log('Next: ' + x),

•     err => console.log('Error: ' + err),

•     () => console.log('Completed'));

•     Observable.

Error handling

•     We should always handle errors

•     Chain the .catch method on an observable

•     Pass in a callback with a single error argument

•     this.http.get('users.json')

•     .catch(error => {

•     console.error(error);

•     return Observable.throw(error.json().error || 'Server error');

•     });

Using Promise

•     Promise is another way we can hit a network url and assess the results. Promise is asynch ,that it waits for the response.

•     We can chain any HTTP with toPromise

•     Then we can use .then and .catch to resolve the promise

•     Headers can be added,post of get can be done.

•     this.http.get('users.json')

•     .toPromise()

•     .then(res => res.json().data) //handle the data

•     .then(users => this.users = users)

•     .catch(this.handleError);/if error

Adding Headers

•     Import Headers and RequestOptions:

•     import {Headers, RequestOptions} from 'angular2/http';

•     Headers are an instance of the Headers class

•     Pass in an object with each header as a key-value pair

•     Used mainly to pass security token params

•     Then pass this Headers instance into a new RequestOptions

•     instance

•     let headers = new Headers({ 'Content-Type': 'application/json' });

•     let options = new RequestOptions({ headers: headers });

•     this.http.post('users.json', '{}', options);

Pipes

•     •What are Pipes?

•     • Built-in Pipes

•     • Custom Pipes

•     • Async Pipes

What are pipes

•     A pipe takes in data as input and transforms it to a desired

•     output

•     We use them in our templates with interpolation:

•     <p>User created on {{ created_at | date }}</p>

•     Include parameters to a pipe by separating them with a colon:

•     <p>User created on {{ created_at | date:"MM/dd/yy" }}</p>

•     Pipes are chain-able:

•     <p>User created on {{ created_at | date | uppercase }}</p>

Build in Pipes

•     DatePipe

•     <p>User created on {{ user.created_at | date }}</p>

•     UpperCasePipe

•     <p>Middle Initial: {{ user.middle | uppercase }}</p>

•     LowerCasePipe

•     <p>Username: {{ user.username | lowercase }}</p>

•     CurrencyPipe

•     <p>Price Plan: {{ user.plan.price | currency }}</p>

•     PercentPipe

•     <p>Data Usage: {{ user.usage | percent }}</p>

Build your own custom pipes

•     import { Pipe, PipeTransform } from 'angular2/core';

•     Create a class that implements the PipeTransform interface

•     and includes a transform method:

•     export class ReversePipe implements PipeTransform {

•     transform(value:string, args:string[]) : any {

•     return value.reverse();

•     }

•     }

Pipes for Http calls

•     Resolves async data (observables/promises) directly in the template

•     Skips the process of having to manually subscribe to async methods

•     in the component and then setting those values for the template to

•     bind to

•     Component attribute:

•     asyncAttribute<string> = new Promise((resolve, reject) => {

•     setTimeout(() => resolve('Promise resolved'), 500);

•     })

•     Template: <p>Async result: {{asyncAttribute | async}}</p>