Tuesday, October 25, 2022

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>

Angular tutorial Part 3 - Learn Angular Services and Dependency injection Forms

Angular

Services and Dependency injection
Forms

Dependency Injection

     Dependencies are services or objects that a class needs to perform its function.

     Dependency injection, or DI, is a design pattern in which a class requests dependencies from external sources rather than creating them.

     Angular's DI framework provides dependencies to a class upon instantiation. Use Angular DI to increase flexibility and modularity in your applications.

     We shall see dependency injection using services

Services

     A service is a class with a focusedpurpose. We often create a service to implement functionality that is independent from any particular component.

     Services are used to share the data and logic across components or to encapsulate external interactions such as data access.

     To create a service class there is no need to do anything angulars pecific,noMetadata,naming convention requirement or some functional interface that needs to be implemented.They'rejust plain old classes that you create to modularize reusable code.

     Services are not only beneficial for modularity and single responsibility,but it also makes the code more testable.

     Dataservice is a class that will handle getting and setting data from your data store

Creating injectable service

     Create an injectable service using the command

     Ng generate service myservice in the angular app folder

     It will create the service shell code

     import { Injectable } from '@angular/core';

      @Injectable({ providedIn: 'root', })

     export class myService { constructor() { } }

     The @Injectable() decorator specifies that Angular can use this class in the DI system. Root gives application wide access to service.

 

       We will add business logic to get todays date to the service.

       showTodayDate() {

           let ndate = new Date();

           return ndate;

        }

       To add this service to component  inject a dependency in a component's constructor(), supply a

        constructor argument with the dependency type.

       1. import { MyserviceService } from './myservice.service';

       2.   constructor(private myservice: MyserviceService ){}

 

         

 

Service

       You can also inject service in the main module

       So in the app-module.ts we can inject the service

       import { MyserviceService } from './myservice.service';

        providers: [MyserviceService],

       Component provider and Module provider are different, If its injected in the module provider,it’s available to the whole app,it can also be specifically be injected into a component.

       @Component({ /* . . . */ providers: [UserService] })

 

 

Forms – two ways to create forms in angular

     Reactive forms provide direct, explicit access to the underlying forms object model. Compared to template-driven forms, they are more robust: they're more scalable, reusable, and testable. If forms are a key part of your application, or you're already using reactive patterns for building your application, use reactive forms.

     Template-driven forms rely on directives in the template to create and manipulate the underlying object model. They are useful for adding a simple form to an app, such as an email list signup form. They're straightforward to add to an app, but they don't scale as well as reactive forms. If you have very basic form requirements and logic that can be managed solely in the template, template-driven forms could be a good fit.

 

 

Core classes

     Both reactive and template-driven forms track value changes between the form input elements that users interact with and the form data in  your component model.

     Both reactive and template-driven forms are built on the following base classes.

 

     FormControl tracks the value and validation status of an individual form control.

 

     FormGroup tracks the same values and status for a collection of form controls.

 

     FormArray tracks the same values and status for an array of form controls.

 

     ControlValueAccessor creates a bridge between Angular FormControl instances and built-in DOM elements.

Building a reactive form

     With reactive forms, you define the form model directly in the component class. The [formControl] directive links the explicitly created FormControl instance to a specific  form element in the view, using an internal value accessor.

     import { Component } from '@angular/core';

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

     @Component({ selector: 'app-reactive-favorite-color', template: ` Favorite Color: <input type="text" [formControl]="favoriteColorControl"> ` })

     export class FavoriteColorComponent { favoriteColorControl = new FormControl(''); } //creates new form control instance

 

Direct access to forms model in a reactive form

Template uses ngmodel for binding and not form control instance

Building template form

     In template-driven forms, the form model is implicit, rather than explicit. The directive NgModel creates and  manages a FormControl instance for a given form element.

     import { Component } from '@angular/core';

     @Component({ selector: 'app-template-favorite-color', template: ` Favorite Color: <input type="text" [(ngModel)]="favoriteColor"> ` }) export class FavoriteColorComponent {

      favoriteColor = ''; }

     In a template-driven form the source of truth is the template. You do not have direct programmatic access to the FormControl

Data flowin reactive forms

     The user types a value into the input element, in this case the favorite color Blue.

     The form input element emits an "input" event with the latest value.

     The control value accessor listening for events on the form input element immediately relays the new value to the FormControl instance.

     The FormControl instance emits the new value through the valueChanges observable.

     Any subscribers to the valueChanges observable receive the new value.

Data flow in reactive forms

 

     The user calls the favoriteColorControl.setValue() method, which updates the FormControl value.

     The FormControl instance emits the new value through the valueChanges observable.

     Any subscribers to the valueChanges observable receive the new value.

     The control value accessor on the form input element updates the element with the new value.

Data flow in template forms

 

     The user types Blue into the input element.

     The input element emits an "input" event with the value Blue.

     The control value accessor attached to the input triggers the setValue() method on the FormControl instance.

     The FormControl instance emits the new value through the valueChanges observable.

     Any subscribers to the valueChanges observable receive the new value.

     The control value accessor also calls the NgModel.viewToModelUpdate() method which emits an ngModelChange event.

     Because the component template uses two-way data binding for the favoriteColor property, the favoriteColor property in the component is updated to the value emitted by the ngModelChange event (Blue).

Data flow in template forms

     The model-to-view diagram shows how data flows from model to view when the favoriteColor changes from Blue to Red, through the following steps

 

     The favoriteColor value is updated in the component.

     Change detection begins.

     During change detection, the ngOnChanges lifecycle hook is called on the NgModel directive instance because the value of one of its inputs has changed.

     The ngOnChanges() method queues an async task to set the value for the internal FormControl instance.

     Change detection completes.

     On the next tick, the task to set the FormControl instance value is executed.

     The FormControl instance emits the latest value through the valueChanges observable.

     Any subscribers to the valueChanges observable receive the new value.

     The control value accessor updates the form input element in the view with the latest favoriteColor value.

 

Form Validations

     Reactive forms define custom validators as functions that receive a control to validate.

     Template-driven forms are tied to template directives, and must provide custom validator directives that wrap validation functions.

 

Reactive forms with form controls

     There are three steps to using form controls.

 

     Register the reactive forms module in your application. This module declares the reactive-form directives that you need to use reactive forms.

     Generate a new FormControl instance and save it in the component.

     Register the FormControl in the template.

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

      imports: [ // other imports ... ReactiveFormsModule ], })

Adding form control to component

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

     name = new FormControl('');//create a new instance of form control

     After you create the control in the component class, you must associate it with a form control element in the template.

     Bind the variable using form control

     <label for="name">Name: </label> <input id="name" type="text" [formControl]="name">

     Display the value

     <p>Value: {{ name.value }}</p>

 

     updateName() { this.name.setValue('Nancy'); }

     Updates the value from a component method

     <button (click)="updateName()">Update Name</button>

     Method binding to update the variable

Form Group controls

     Forms typically contain several related controls. Reactive forms provide two ways of grouping multiple related controls into a single input form.

     A form group defines a form with a fixed set of controls that you can manage together. Form group basics are discussed in this section. You can also nest form groups to create more complex forms.

     A form array defines a dynamic form, where you can add and remove controls at run time. You can also nest form arrays to create more complex forms. For more about this option, see Creating dynamic forms.

 

Building a form group control

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

     To add a form group to this component, take the following steps.

 

     Create a FormGroup instance.

     Associate the FormGroup model and view.

     Save the form data.

Creating a form group

     import { Component } from '@angular/core';

     import { FormGroup, FormControl } from '@angular/forms';//import the formgroup

 

     @Component({

       selector: 'app-profile-editor',

       templateUrl: './profile-editor.component.html',

       styleUrls: ['./profile-editor.component.css']

     })

     export class ProfileEditorComponent {

       profileForm = new FormGroup({  //instantiate new form group

         firstName: new FormControl(''), //within from group instantiate new form control

         lastName: new FormControl(''),

       });

     }

Associate the FormGroup model and view

     Build the form ,associate the formgroup and submit the data.

 

     <form [formGroup]="profileForm" (ngSubmit)="onSubmit()">

       <label for="first-name">First Name: </label>

       <input id="first-name" type="text" formControlName="firstName">

 

       <label for="last-name">Last Name: </label>

       <input id="last-name" type="text" formControlName="lastName">

 

     </form>

     In Submit method access the form group values

     onSubmit()

     { // TODO: Use EventEmitter with form value

     console.warn(this.profileForm.value);

      }

There are two ways to update the model value:

       Use the setValue() method to set a new value for an individual

       control. The setValue() method strictly adheres to the structure of the form group and replaces the entire value for the control.

 

       Use the patchValue() method to replace any properties defined in the object that have changed in the form model.

       updateProfile() {

         this.profileForm.patchValue({    firstName: 'Nancy',    address: {      street: '123 Drew Street'    }

         });

       }

 

Validations

     <p>Complete the form to enable button.</p>

     <button type="submit" [disabled]="!profileForm.valid">Submit</button>

     The above mark up allows submission only if form control values are valid. These validation rules will be defined by you using validators.

 

 

Validation in template forms

 

     <input type="text" id="name" name="name" class="form-control"

           required minlength="4" appForbiddenName="bob"      [(ngModel)]="hero.name" #name="ngModel">

 

     <div *ngIf="name.invalid && (name.dirty || name.touched)"    class="alert">  <div *ngIf="name.errors?.required">    Name is required.

       </div>  <div *ngIf="name.errors?.minlength">

         Name must be at least 4 characters long.  </div>  <div *ngIf="name.errors?.forbiddenName">

         Name cannot be Bob.

       </div>

 

     </div>

Validation in template forms

     The <input> element carries the HTML validation attributes: required and minlength. It also carries a custom validator directive, forbiddenName. For more information, see the Custom validators section.

 

     #name="ngModel" exports NgModel into a local variable called name. NgModel mirrors many of the properties of its underlying FormControl instance, so you can use this in the template to check for control states such as valid and dirty. For a full list of control properties, see the AbstractControl API reference.

 

     The *ngIf on the <div> element reveals a set of nested message divs but only if the name is invalid and the control is either dirty or touched.

 

     Each nested <div> can present a custom message for one of the possible validation errors. There are messages for required, minlength, and forbiddenName.

Validation in Reactive forms

     Built in validators can be used at the form control level to validate inputs

     Custom validators can also be used to validate. Lets look at an example

     name: new FormControl(this.hero.name, [ Validators.required,  Validators.minLength(4), //these 2 validators check for required and length of input.

      forbiddenNameValidator(/bob/i) // <-- Here's how you pass in the custom validator. ]),

Building a custom validator

      forbiddenNameValidator(nameRe: RegExp): ValidatorFn {

          //first line creates a function which accepts a regularexp.//It also implements interface validatorfn   .A function that receives a control and synchronously returns a map of validation errors if present, otherwise null.

          //the interfae implemented method.is passed the control.valuereturn (control: AbstractControl): ValidationErrors | null => {

              return (control: AbstractControl): ValidationErrors | null => {

                const forbidden = nameRe.test(control.value)//this will return true or false    nbased on whether the control,value, matches with the regular expression          // added in the validatr

                return forbidden ? {forbiddenName: {value: control.value}} : null;

              };

      }//imports of validator,validationerrors,validationfn required from angular/forms

     Ternary operator

     function getFee(isMember) {  return (isMember ? '$2.00' : '$10.00');}

     If true 2 ,if null or false 10

Creating a user registration form demo

     ng g component formapp  to generate form app