Sunday, October 20, 2019

My Angular JS Short Summary Notes




0- Basic Commands of angular is as follows
npm install -g npm@latest // to update npm version
node -v
npm -v
npm install -g @angular/cli@latest   // install latest angular
ng new my-app-name // create new app
ng serve --open // run the app in the browser
ng generate component component_name
ng generate module module-name
        ng generate component module-name/component-name // to generate the component on a specific module rather than app.module.ts
ng generate service service-name // this cmd will not add the service to the providers array in App module.ts you need to register it manually
ng build // builds and generates the dist directory that contains the deployments files
ng g class class-name // generate only a class that can be used as a model object


1- To evaluate a one way data binding expression use the following  {{ value * 3 }} where value is a member variable inside the class ts file

2- To pass a value from parent component to child component , put in the child component the directive @Input("PropertyName")
and the calling component will be like <CHILD-TAG PropertyName="Mahmoud"></CHILD-TAG>

3- To Pass a member variable from parent to child and this member variable is not just a string value passing , use the following syntax
<CHILD-TAG [PropertyName]="Mahmoud"></CHILD-TAG> where Mahmoud in this case is not just a string passed , it's the name of the property
or object defined in the parent component class ts , the child component will remain able to accept the new passed object with the same
@Input("PropertyName") myObject : User;  way

4- to loop and display multiple items :
<p *ngFor="let item of user.phones">item</p> where user.phones is an object that contains array of string phones

5- to check the condition to display a div or not use ngIF
<div *ngIf="user.phones.length > 0">
</div>

6- To create an initialization for member variables in a class just use the ngOnInit() lifecycle hook to do your code as it is called
After the constructor of the class invoked.

7- style classes applied to the component css file applies only for this component and not globally because angular adds an extra property
for HTML tags by default for every component and style the classes using this property in the back scene ... this property value changes from
one component to another in the same project.

8- to execute a method in the ts class file from a button on the html use the following syntax , we surrounded the click with () to differntiate it from html default click event
<button (click)="doMyCode()"> Press Me </button>

9- To create a two way data binding between the page html and the class ts file use the ngModel as below to evaluate the property name text inside the "" which is defined inside the ts file class
<input type="text" [(ngModel)]="propertyName"> </input> , and to use the ngModel we need to import the FormsModule in the app.module.ts file Imports.

10- We can create multiple modules in angular , we can use them inside each others provided that we will add them to the imports part of the parent module and components that to be used in other
modules should be exported first in their containing module.

11- Service classes has the annotation @Injectable() which means that this is a service can be injected into the constructor of other services or component classes.

12- Dependency Injection is a way that services could be injected into other services or components , angular will instantiate the service
and provide it to the consuming class as below, the private will create an instance variable for the class and inject it with the injected class

constructor(private svc: TestService)
{
this.svc.doSomething();
}

13- To use HttpClient service we need to put HttpClientModule in the imports section of the app.module.ts
import { HttpClientModule } from '@angular/common/http';
@NgModule({
  declarations: [
    AppComponent,
    HelloWorldComponent
  ],
  imports: [
    BrowserModule ,
    HttpClientModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
and in the component class :-
import { HttpClient } from '@angular/common/http';

constructor(private http : HttpClient)
  {
  }
 ngOnInit()
  {
    let obs = this.http.get('http://172.16.3.35:8001/myweb/mms/routeschedule' ,
    {
       headers: new HttpHeaders({
      'Authorization': 'Basic bWdhYnIg=',
      'Content-Type': 'application/json'})
     }
    );
    obs.subscribe( res=> {
      console.log(res);
      this.response = res.toString();
    } );
  }

14- We can use the following syntax when we are not sure of the existence of the name property on the response object
{{response?.name}}

15- to create a server that hosts a certain build directory on your machine rather than the developement server
ng build --prod
npm install http-server -g
http-server dist/build-proj/  // this opens the server and hosts the files in this directory which is the build files


16- Routing is done based on certain URL patterns , the views will be switched between components but all will be in the same page view (SPA).


17- creating application with routing enabled

ng new app-name --routing

18- Simple routing code

import {Route , RouterModule } from '@angular/router';
const routes : Route[] =
[
{path: '' , redirectTo: '/view1' , pathMatch: 'full'}, // redirect to default path
{path: 'view1' ,  component : View1},
{
 path: 'view2' , // For this parent component html we need to add another
<router-outlet></router-outlet>
 tag to display the second level child components
 component : View2 ,
 children :[
           {path: '' , redirectTo: 'view3' , pathMatch: 'full'},  // default child route is specified and note that there is no '/' needed
           {path: 'view3' ,  component : View3} ,   // child route that will be accessed with this URL /view2/view3
           {path: 'view4' ,  component : View4} ,    // child route that will be accessed with this URL /view2/view4
           {path: '**' , component: ErrorNotFoundComponent } // wild card for child level routes
  ]
},
{path: '**' , component: ErrorNotFoundComponent }    // anything else not mentioned above just display the Not Found Component
];

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


19- On the main page html there will be a tag called
<router-outlet></router-outlet>
  that switches between routed components

20- You can specify the routing links with this way , but it will make a full page refresh
<a href="/view1">view 1</a>
<a href="/view2">view 2</a>

intsead you need to specify the links with this way so as not to make a full page refresh
<a routerLink="view1">view 1</a>
<a routerLink="view2">view 2</a>

or dynamically as
<a *ngFor="let route of routes" [routerLink]="route.url">{{route.name}}</a>


21-  to truncate a certain displayable value to certain lenght you can use angular pipes as below {{ user.desc | truncate : [30]}}
ng g pipe truncate //  this will create a pipe class and register it in app.module.ts
Inside the class u will find a transform method that takes the value as 1st param and arguments as a 2nd param
 or if you want to call the pipe programmatically from the component class you can do the following :
- add the pipe class to the providers array of app.module.ts
- Dependency inject the pipe class single instance into the component class by specifying it in the constructor of the component
- in ngOnInit() use the pipe class reference to call the transform method on the values you want.


22-
this.pages = new Array(this.numberOfPages); // creating array of certain length
*ngFor="let page of pages ; index as i"  // Syntax to create a loop and get the index

23- Emitting events happens from child components to parent ones..
on the child component use :
 @Output() pageNumberClicked = new EventEmitter<number>();  //where number is the type of data to be emitted.
then on the method that invokes the event  on the child side
this.pageNumberClicked.emit(pageNumber);

on the parent side we will listen to the child pageNumberClicked event
<app-paginator (pageNumberClicked)="handleEventOnParent($event)" [numberOfPages]="blogPosts.length"> </app-paginator>

24- ViewEncapsulation is a feature either set to Emulated which is the default value or NONE.
If Emulated , the css classes will be isolated from one compnent to another but NONE keeps the components shares the CSS classes

25- To bind a child component in the html to the parent component class , use local refrence and @ViewChild()

@ViewChild('compLocalRef') blogPostTileComponent : BlogPostTileComponent;
and the html as <app-blog-post-tile #compLocalRef ></app-blog-post-tile>

26- If you want to apply a style sheet class for a certain component based on an expression just do the following

<div [ngClass]="'fav' : post.isFavourite"> </div>

Where 'fav' is the name of the syle sheet class and post.isFavourite is an expression that returns true / false


27- generate a directive class to be put on certain elements , directives are used to change the dom element they are applied to
That's why they accept an elementRef object in their constructor to manipulate the dom of the element they are applied to.

ng g directive directive-name


28- <ng-content></ng-content> tells angular that you are interested in the HTML dom elements that you place inside the component openning and closing tags on the parent page.
ex: at the parent page
<component-tag>
<h1>Heading</h1>
</component-tag>

and at the child component just put the <ng-content></ng-content> to display the h1 tag and all dom elements inside the component's tag


29- How to Pass parameters to Angular Route

We can define parameter by adding forward slash followed colon and a placeholder (id , id1 , id2) as shown below in the routes array of the app.routing.module.ts

{ path: 'product/:id/:id1/:id2', component: ProductDetailComponent }

We, now need to provide both path and the route parameter routerLink directive.

This is done by adding the productID as the second element to the routerLink parameters array as shown below

<a [routerLink]="['/Product', ‘2’]">{{product.name}} </a>

OR

<a [routerLink]="['/Product', product.productID]">{{product.name}} </a>

Which, dynamically takes the value of id from the product object.

Finally, our component needs to extract the route parameter from the URL

This is done via the ActivatedRoute service from angular/router module to get the parameter value
The ActivatedRoute is a service, which keeps track of the currently activated route associated with the loaded Component.

import { ActivatedRoute } from '@angular/router';

Then inject it into the component using dependency injection

constructor(private _Activatedroute:ActivatedRoute)

The Angular adds the map all the route parameters in the ParamMap object, which can be accessed from the ActivatedRoute service

There are two ways in which you can use the ActivatedRoute to get the parameter value from the ParamMap object.

- Using Snapshot

this.id=this._Activatedroute.snapshot.paramMap.get("id");

- Using observable

this._Activatedroute.paramMap.subscribe(params => {
    this.id = params.get('id');
});

Use this option if you expect the value of the parameter to change over time.

Why use observable

We usually retrieve the value of the parameter in the ngOninit life cycle hook, when the component initialised.

When the user navigates to the component again, the Angular does not create the new component but reuses the existing instance. In such circumstances, the ngOnInit method of the component is not called again. Hence you need a way to get the value of the parameter.

By subscribing to the observable paramMap property, you will retrieve the latest value of the parameter and update the component accordingly.

check example at the following URL : https://www.tektutorialshub.com/angular/angular-passing-parameters-to-route/

Use the Router to navigate programatically and don't forget to unSubscribe the observable in the ngDestroy() hook

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Router,ActivatedRoute } from '@angular/router';

import { ProductService } from './product.service';
import { Product } from './product';


@Component({
  templateUrl: './product-detail.component.html',
})

export class ProductDetailComponent
{

   product:Product;
   id;
 
   constructor(private _Activatedroute:ActivatedRoute,
               private _router:Router,
               private _productService:ProductService){
   }

 
   /* Using snapshot */
   // ngOnInit() {

   //    //This still works but is deprecated
   //    //this.id=this._Activatedroute.snapshot.params['id'];

   //    this.id=this._Activatedroute.snapshot.paramMap.get("id");

     
   //    let products=this._productService.getProducts();
   //    this.product=products.find(p => p.productID==this.id);
   // }
 

   /* Using Subscribe */
 
   sub;

   ngOnInit() {

      this.sub=this._Activatedroute.paramMap.subscribe(params => {
         console.log(params);
          this.id = params.get('id');
          let products=this._productService.getProducts();
          this.product=products.find(p => p.productID==this.id);  
      });

      // This params is deprecated

      //this.sub=this._Activatedroute.params.subscribe(params => {
      //    this.id = params['id'];
      //    let products=this._productService.getProducts();
      //    this.product=products.find(p => p.productID==this.id);  
      //
      //});
   }

   ngOnDestroy() {
     this.sub.unsubscribe();
   }
 
   onBack(): void {
      this._router.navigate(['product']);
   }
}


30- Angular JWT Token Authentication complete example


https://jasonwatmore.com/post/2019/06/22/angular-8-jwt-authentication-example-tutorial




31- Angular Forms

https://appdividend.com/2019/06/07/angular-8-forms-tutorial-angular-reactive-and-template-forms-example/

Reactive forms in Angular 8
Reactive forms or Model-driven forms are more robust, scalable, reusable, and testable. If forms are the key part of your application, or you’re already using reactive patterns for building your web application, use reactive forms.

In Reactive Forms, most of the work is done in the component class.

Template-driven forms in Angular 8
Template-driven forms are useful for adding the simple form to an app, such as the email list signup form. They’re easy to add to a web app, but they don’t scale as well as the reactive forms.

If you have the fundamental form requirements and logic that can be managed solely in the template, use template-driven forms.

In template-driven forms, most of the work is done in the template.

Example of Template-driven form in Angular 8
Okay, now let’s install the fresh Angular 8 application.

Then go to an app.module.ts file and add the following code.

// app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';

import { AppComponent } from './app.component';

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

In the above file, we have imported the FormsModule from the @angular/forms library.

Now, we can use the FormsModule inside our app.component.ts file.

// app.component.ts

import { Component, OnInit } from '@angular/core';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
   constructor() { }
   ngOnInit() {
   }
   onClickSubmit(formData) {
      alert('Your Email is : ' + formData.email);
   }
}
In this file, we have defined on onClickSubmit function, which will trigger when the user clicks the submit button on the form. The function also accepts one argument called formData, which is the object of the entire form values.

Through that formData object, we can access all the form field values. In our case, I only need the user’s email id. In the general scenario, we want to pass that object to the POST request to the backend server to store the user’s data.

Now, only remaining thing is to write the HTML of the app component. So, write the following code inside the app.component.html file.

<form #login = "ngForm" (ngSubmit) = "onClickSubmit(login.value)" >
  <input type = "text" name = "email" placeholder = "email" ngModel>
  <br/>
  <input type = "password" name = "pwd" placeholder = "password" ngModel>
  <br/>
  <input type = "submit" value = "submit">
</form>

We have created the web form with input tags having email, password and the submit button. We have assigned a type, name, and placeholder attributes to it.

In the template driven forms, we need to create a model form controls by adding the ngModel directive and the name attribute. Thus, whenever we want Angular to access our data from forms, add ngModel to that tag as shown above. Now, if we have to read an email and password, we need to add a ngModel across it.

If you close look at the form, we have also added the ngForm to the #login. The ngForm directive needs to be added to a form template that we have created.

Atlast, We have also added the function onClickSubmit and assigned login.value to it.


Model-driven or Reactive Forms in Angular 8
In the model-driven form, we need to import a ReactiveFormsModule from @angular/forms and use the same in the imports array.

There is a change which goes in app.module.ts. See the app.module.ts file.

// app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    ReactiveFormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
In the app.component.ts file, we need to import the few modules for the model-driven form. For example, import { FormGroup, FormBuilder } from ‘@angular/forms’.


See the following app.component.ts file.

// app.component.ts

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder } from '@angular/forms';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  angForm: FormGroup;
  constructor(private fb: FormBuilder) {
    this.createForm();
  }
  createForm() {
    this.angForm = this.fb.group({
      email: [''],
      password: ['']
    });
  }
  onClickSubmit(email, password) {
    alert('Your Email is : ' + email);
  }
   ngOnInit() {
   }
}


In the above code, we have used a FormBuilder to create a form and initialize the value of two fields which is empty.

We have also defined one function called onClickSubmit() which accepts the two parameter email and password.

So,  when the user pressed the submit button, we got the values here and then we send these values with the POST request to the backend server.

Finally, write the app.component.html file.

<form [formGroup]="angForm">
  <input type = "text"
        name = "email"
        placeholder = "email"
        formControlName="email"
        #email>
  <br/>
  <input type = "password"
        name = "pwd"
        placeholder = "password"
        formControlName="password"
        #password>
  <br/>
  <input type = "submit"
          value = "submit"
          (click) = "onClickSubmit(email.value, password.value)" >
</form>

One of the advantages of the Model-driven approach is that the Validations become very easy.

No comments:

Post a Comment