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>