---
# System prepended metadata

title: Angular CLI

---

Angular CLI
=
Installation
-
**Npm** - package manager
```bash=
npm install -g npm
```
**NodeJS** - Server side framework
https://nodejs.org/en/

**ng-cli** - Angular CLI prompt
```bash=
sudo npm uninstall -g angular-cli @angular/cli
npm cache clean 
sudo npm install -g @angular/cli
```
**Bootstrap** - CSS framework
Install inside the project's folder
```bash=
npm install --save bootstrap@3
```
Add the bootstrap’s path to .angular-cli.json
`../node_modules/bootstrap/dist/css/bootstrap.min.css`

This does 2 things: add the import to the html head 
Angular launches the & app via bootstrap app.module.

Debugging
-
**Inspect** - `CTRL + SHIFT + I`
Pause debugger to get values

**Sources**
Typescript is not running at the browser, Javascript is!
we need to access Typescript in order to debug.
- Pause in debugger and check for values
`sources > webpack > src > app …`

**Augury chrome extension:**
- App analyzer
- Component properties
- Component hierarchy graph

Project handling
-
**Create new project**
```bash=
ng new project-name
cd project-name
ng serve
--port=4200 #localhost:4200
--poll=2000 # enables files watching in ms
```
**create new component**
```bash=
ng generate component component-name
ng g c component-name
```
**create a nested component**
```bash=
ng g c auth/signup
--spec false # to disable generation of component’s test file
```

**Optimize the app**
Angular built in tool for production
```bash=
ng build --prod --aot
```
Ahead of Time Compilation (compiled on server instead on browser's accessing, part of the process is compiling the HTML files into JS since it is faster to access JS then DOM)


++Running an imported project fails (ng serve)?++
You seem to not be depending on "@angular/core". This is an error.
inside project folder run: `npm install`

<hr>
<hr>
<hr>


Angular Basics
=

General structure
-
#### String interpolation

`{{ serverId }}` 

#### Ng-Model

Connects components together.

#### Template

1. Short HTML snippet (wrap with tilda parenthesis for multiple rows).
```htmlmixed
template: '<p>Hello</p>'`
```
2. Connecting to HTML file.
```htmlmixed
templateUrl: './app.component.html'
```

### Attribute

```typescript=
// `<app-server></app-server>`
selector: 'app-server'
// `<div class="app-server">`
selector: '[app-server]'
// dot (.) like in css
selector: '.app-server'
```
#### Data Binding

Button disabled dynamically according to allowButton property
```htmlmixed=
<button class="button" [disabled]="allowButton">
    Add Server
</button>
```
#### Event binding

Button onclick 
```htmlmixed=
<button class="button" (click)="changePrint()">
    {{ printProperty }}
</button>
```
Examples:
The MDN (Mozilla Developer Network) offers nice lists of all properties and events of the element you're interested in. Googling for YOUR_ELEMENT properties  or YOUR_ELEMENT events  should yield nice results. 

#### Two way binding

React to changes in different location on code by listening on events 
1. Import formsModule to enable it.
2. Add 

#### Two Way

```htmlmixed=
<input
    type="text"
    class="form-control"
    [( ngModel )] = "serverName">
```

#### One way

```htmlmixed=
<input
    type="text"
    class="form-control"
    (input)= "onUpdate($event)">
<p>{{ serverName }}</p>
```
3. Add Listener function
```typescript=
onUpdate(event: Event){ //Event is TS type
    this.serverName = (<HTMLInputElement>.event.target).value;
}
```

* Communication between components?

* Create a Shared folder -  for sharing elements between features. (shoppingList & Recipe)

<hr>
Syntax
-
#### Typescript typing
With (but not nessesary before TS infers it) 
`serverID: number = 17`

#### Esx function
```typescript=
SetTimeout( funcion, ms)

setTimeout( () ==> {
    this.property = true;
}, 2000);
```

#### Array
```typescript=
servers: ['serverA', 'serverB'];
// add to array
this.servers.push('name')
// get - shallow copy
this.servers.slice('name')
```

#### Date
`new Date()`
#### Operators
`=== is like ==` except it doesn't accept type conversion
`true == 1` but `true (!) === 1`

<hr>
CSS Encapsulation
-
#### View encapsulation
enable/disable css attribute on other components.
add to the component decodator @
`encapsulation:ViewEncapsulation.None' child css is globally now
`encapsulation:ViewEncapsulation.Emulated' encapsulated

<hr>
Models
-
Vanilla TypeScript class
```typescript=
export class Recipe{}
```
- object - can be instanceiated
- can make array of objects `Recipe[]`

#### Two ways to construct a model (will do the same)
```typescript=
export class Ingredient {
    public name: string;
    public amount: number;
    
    constructor(name: string, amount: number){
        this.name = name;
        this.amount = amount;
    }
}
```

or

```typescript=
export class Ingredient {
    constructor(public name: string,public amount: number){}
}
```
Pipes
-
* Find all options in https://angular.io/api?query=pipe
A way to write display-value transformations that you can declare in your HTML.
Outputs a property in a different way without changing its value.
```htmlmixed
// Max --> MAX
{{ username | uppercase }}
// Mon Aug 08 1920 00:00:00 GMT +0200 (CEST) --> Aug 8, 1920
{{ server.started | date }}
```
#### Configure a pipe
By adding a colon with a value in camelCase (multiple attributes can be added in a chain colons, pipes can be chained also with the pipe symbol `|` in between)
```htmlmixed
{{ server.started | date:'fullDate' }}
```
* Order is important
#### Create new pipe (with configureable parameter)
```shell
ng g pipe
```
```typescript=
import { Pipe ,PipeTransform } from '@angular/core';

@Pipe({
    name: 'shorten'
})

export class ShortenPipe implements PipeTransform {
    transform(value: any, limit: number) {
        return value.substr(0,limit);
    }
}
```
```htmlmixed
{{ name | shorten:5 }}
```
* Pure & Impure pipes
Updating a filter on every change, but data is not updated every time, this saves us usage. (video #233)
* Async pipes - changes the output on async
`{{ status | async }}`
* Sort pipe
```typescript=
transform(value: any, propName: string): any {
    return value.sort((a, b) => {
       if(a[propName] > b[propName])
           return 1;
       else
           return -1;
    });
}
```
<hr>
Deployment on server
=
* Optimize the app
    * Angular built in tool for production - minifies code.
    * Ahead of Time Compilation (compiled on server instead on browser's accessing, part of the process is compiling the HTML files into JS since it is faster to access JS then DOM)
    `ng build --prod --aot`
* Set the correct <base> element
for `example.com/my-app`, configure `<base href="/my-app/">`
or with the CLI `ng build --prod --aot --base-href /my-app/`
* Make sure the server always returns `index.html`
In case of an error the server doesn't know the routes, returning `index.html` lets angular the chance to take over and return a built-in error page.

* On AWS console (free for 12 month)
upload `dist/*` (build output files).
Now just enter the URL given in Static website hosting.

___
Components
=
A section in the app, that we can reuse in the app or in other apps.

Binding components
-
* Exposing component property to the a **Parent** component (in JS a property is accesible only from inside the class)
* Add a decorator
```typescript=
@Input() element: {
    type: string,
    name: string,
    content: string
}
```
And import `Input` from angular/core
Inside the Parent component:
On Parent HTML: element is the property name of the child component
```htmlmixed=
<app-server-element
        *ngFor="let serverElement of serverElements"
        [element]="serverElement"
      ></app-server-element>
```

```typescript=
// binds element component to the name srvElement
// (to be used outside the app)
@Input('srvElement') element:...
```

* listen to a object creation on Parent component (when function that creates in the child it is called, implement it in the parent function done after its done in child)
* In child.ts - pass `serverCreated` to be listened from Parent, event emitter - create events, of course import output and emitter, in the <> specify a type.
```typescript=
@Output() serverCreated = new EventEmitter<{ServerName: string, serverContent: string}>();
@Output() blueprintCreated = new EventEmitter<{ServerName: string, serverContent: string}>();

newServerName = '';
newServerContent = '';

constructor() { }

ngOnInit() { }

onAddServer() {
    this.serverCreated.emit({
      ServerName: this.newServerName,
      serverContent: this.newServerContent,
    });
}
```
in Parent.ts - get `serverData`, a js object from `$event` and add to array
```typescript=
onServerAdded(serverData: {ServerName: string, serverContent: string}) {
    this.serverElements.push({
      type: 'server',
      name: serverData.ServerName,
      content: serverData.serverContent
    });
  }
onBlueprintAdded(blueprintDate: {ServerName: string, serverContent: string}) {
    this.serverElements.push({
      type: 'blueprint',
      name: blueprintDate.ServerName,
      content: blueprintDate.serverContent
    });
  }
```
parent HTML - listen on: `serverCreated`, run method `onServerAdded`, get the object binding `$event`
```htmlmixed=
<app-cockpit
    (serverCreated)="onServerAdded($event)"
    (blueprintCreated)="onBlueprintAdded($event)"
    ></app-cockpit>
```

Other ways to data bind:
1. Local reference:
substance to databinding - eliminate the need for property.
get access to a element in the template and use it or pass it to typescript code

2. Projecting content into a component
Extract component's code to parent (for reusabillity).
inside component template replace this
```htmlmixed=
<p>
      <strong
              *ngIf="element.type === 'server'" style="color: red">
          {{ element.content }}</strong>
      <em *ngIf="element.type === 'blueprint'">
          {{ element.content }}</em>
</p>
```
with `<ng-content></ng-content>` to enable component code hooking inside it's declaration (`<server-element>HERE</server-element>`)


___

Directives
=
Structure directives (with *ngDirectiveName)
-
* cannot make multiple structure directive on one HTML element


#### ngIf
```htmlmixed
<p *ngIf="serverCreated"> Server created!</p>

// for multiple elements use ngIf without the *
<ng-template [ngIf]="!authService.isAuthenticated()">
      <li><a routerLink="/signup">Register</a></li>
      <li><a routerLink="/signin">Login</a></li>
</ng-template>
```

If-else
```htmlmixed=
<p *ngIf="serverCreated"; else noServer> Server created!</p>
<ng-template #noServer>
<p> No server </p>
</ng-template>
```
#### ngFor
```htmlmixed
<servers-app *ngFor="let server of servers"> </servers-app>
```
get iteration index
```htmlmixed=
let server of servers; let i=index
```

#### ngSwitch
Great solution to replace a bunch of `ngIf`s

<hr>

Attribute directives
-
#### ngStyle
We will use property binding on this directive
```htmlmixed
<p [ngStyle]="{backgroundColor: getColor()}">{{ server }} </p> //camelCase
```
```htmlmixed=
<p [ngStyle]="{'background-color: getColor()'}"> {{ server }} </p>//CSS style
GetColor(){
   Return this.status === 'online ? 'green' : 'red';
}
```
**ngClass**
dynamically add CSS class. create it on component and condition it in html.
in order for this to work in ngFor, condition ngClass with object's field and not entire component. (ass3)
> component.ts
```typescript=
styles: ['
.online{ color: white;}
']
```
> component.html
```htmlmixed=
<p [ngClass]="{online: serverStatus === 'online'}">
    Server </p>
```

<hr>

### Creating new Directives
* Manually or with `ng g directive 'name'`
* better creating it with renderer
* More actions beside setStyle - https://angular.io/api/core/Renderer2
* Creating a structural directive is also possible - see on course
1. create the folder & file (as in image)
2. create the class
```typescript=
import { Directive, ElementRef, OnInit } from "@angular/core";
@Directive({
    selector: '[appBasicHighlight]'
})
export class BasicHighlightDirective implements OnInit {
    constructor(private elementRef: ElementRef){
    }
    ngOnInit() {
        this.elementRef.nativeElement.style.backgroundColor = 'green';
    }
}
```
or with render:
```typescript=
constructor(private elRef: ElementRef, private renderer: Renderer2) { }

  ngOnInit(){
    this.renderer.setStyle(this.elRef.nativeElement, 'background-color', 'pink')
  }
```
Listen to host events: `mouseenter/mouseleave` is the event name
```typescript=
  @HostListener('mouseenter') mousehover(eventData: Event){
    this.renderer.setStyle(this.elRef.nativeElement, 'background-color', 'lightGreen')
  }
  @HostListener('mouseleave') mouseleave(eventData: Event){
    this.renderer.setStyle(this.elRef.nativeElement, 'background-color', 'pink')
  }
```
Bind to host events - *Stronger*: bind the event `style.backgroundColor` to the element property (on the right). must set an initial value to avoid error.
```typescript=
export class BetterHighlightDirective implements OnInit{
  @HostBinding('style.backgroundBolor') backgroundColor: string = 'transparent';
  constructor(private elRef: ElementRef, private renderer: Renderer2) { }
  @HostListener('mouseenter') mousehover(eventData: Event){
    this.backgroundColor = 'lightGreen';
  }
  @HostListener('mouseleave') mouseleave(eventData: Event){
    this.backgroundColor = 'ping';
  }
}
```
Adding private is a TS shourcut for make this element a property of the class and automatically assign the value given on constructions
Also, can add a CSS class by listening to click (on course)
3. add to app declaration - just like with components
```typescript=
import { BasicHighlightDirective } from './basic-highlight/basic-highlight.directive';
@NgModule({
  declarations: [
    AppComponent,
    BasicHighlightDirective,
```
4. use it:
```htmlmixed=
<p appBasicHighlight> Style me! </p>
```


___

Elements
=
#### Button
* type
button: The button is a clickable button
submit: The button is a submit button (submits form-data)
reset: The button is a reset button (resets the form-data to its initial values)

#### Lifecycle hooks:
1. ngOnChanges - called when binded object is changed
2. ngOnInit - called when object is instantiated
3. ngDoChange - called on each change detection run (in development mode, called twice on object instantiation)
4. ngAfterContentInit - called only once, when ng-content is is projected
5. ngAfterContentChecked - called after each change detection cycle
6. ngAfterViewInit - like the above
7. ngAfterViewChecked - like the above
8. ngOnDestroy - called when object is deleted.

* They all should be imported from core and implemented by the component
```typescript=
export class ServerElementComponent implements
    OnInit, OnDestroy { ...
```
```typescript=
import {
  Component,
  OnInit,
  OnDestroy }
  from '@angular/core';
```
* To access DOM elements with @ViewChild, we can see the content only after (6) was called
* To access DOM content with @ContentChild, we can see the content only after (4) was called

* setInterval() - to perform an action on time intervals.


___

Services
=
* Optimize the app when multiple components use pretty much the same service.
* Do it by injecting the service to the component
* Hierarchical Injection - if we provide in:
`AppModule`: same instance of service is available Application-wide
`AppComponent`: available for all components (but not for other services)
`AnyOtherComponent`:` only for him
To use it in the hierarchical way - provide only on Parent module but keep constructor on childs.
* Handle users for example - holds database on actions on it
---

1. The service - plain Javascript class that contain function that serves
```
export class LoggingService{
    logStatusChange(status: string){
        console.log("status has changed" + status);
    }
}
```
2. Instantiate the service - get Angular to do this for us.
```
@Component({
    providers: [LoggingService]
})
export class AppComponent{
    constructor(private loggingService: LoggingService) {}

    onSomeFunction{
        this.loggingService.logStatusChange('status changed');
    }
}
```
3. add to app.module declarations (like components)

---

* Inject service to a service
Add a decorator to the service
`@Injectable()`

* Communication between components through a service (Listening to events)
On the Service
```typescript=
statusUpdated = new EventEmitter<string>();
```
Emit on component A
```typescript=
this.accountService.statusUpdated.emit(status);
```
Listen on Component B
```typescript=
this.accountService.statusUpdate.subscribe(
    (status: string) => alert('New Status' + status)
);
```

___

Models
=
Vanilla TypeScript class
```typescript=
export class Recipe{}
```
- object - can be instanceiated
- can make array of objects `Recipe[]`

#### Two ways to construct a model (will do the same)
```typescript=
export class Ingredient {
    public name: string;
    public amount: number;
    
    constructor(name: string, amount: number){
        this.name = name;
        this.amount = amount;
    }
}
```

or

```typescript=
export class Ingredient {
    constructor(public name: string,public amount: number){}
}
```

___

Routes
=
> app.module.ts
```typescript=
import { Routes } from '@angular/router';

// declare routes
const appRoutes: Routes =[
    { path: '', component: HomeComponent }
    { path: 'users', component: UsersComponent }
    { path: 'servers', component: ServersComponent }
    //in case we want the opening page to redirect to servers - we will do:
    { path: '', redirectTo: '/servers', pathMatch: 'full' }
    // pathMatch must be added or else this cause an error:
    // because '' matches every route
]

// register the routes to our angular app
imports: [
    RouterModule.forRoot(appRoutes)
]
```
when `localhost:4200/users` reached, `UserComponent` is called
this register the routes to our angular app

> template.html
```htmlmixed=
<li role="presentation">
    <a
        routerLink="/"
        routerLinkActive="active"
        [routerLinkActiveOptions]="{exact: true}"
        > Home </a> </li>
<li role="presentation">
    <a
        routerLink="/users"
        routerLinkActive="active"
        > Users </a> </li>
<li role="presentation">
    <a
        [routerLink]="['/users','10','Anna']" // `/users/10/Anna`
        routerLinkActive="active"
        > Users </a> </li>
<router-outlet> </router-outlet>
```
`routerLink` - Avoid reloading on each route activation
`routerLinkActive` - Mark as active only when contains this path
`routerLinkActiveOptions` - only at this exact path `/` mark as active

Trigger route from within our code - load a route automatically on button click
-
1. Inject router into the component
2. Call a function from the button
```htmlmixed=
<button class="btn btn-primary" (click)="onLoadServers">
     Load Servers
</button>
```

```typescript=
import { Router, ActivatedRoute } from `@angular/router`;

constructor(
            private router: Router
            private route: ActivatedRoute) { }

onLoadServers() {
    this.router.navigate(['/servers']);
    // absolute path. navigate takes an array of elements in the path
    
    this.router.navigate(['servers'], {relativeTo: this.route});
    // let navigate know on what route it is currently in
    // reload the page
    // results with /servers/servers
}
```
Passing parameter to Routes
-
> app.module

```typescript=
    { path: 'users/:id/:name', component: UsersComponent }
    // dynamic id, name
```
> app.component.ts
```typescript=
ngOnInit() {
    this.user = {
        id: this.route.snapshot.params[id],
        name: this.route.snapshot.params[name]
        // retrieve id and name into component dynamically from route path
    }
    // Or with + to convert string from route to number
    const id =+this.route.snapshot.params['id'];
    this.user = this.UserService.getUser(id);
    
    // observer - deal with asynchronous events and
    // be fired whenever new data is sent to this route
    // not executed on ngOnInit
    this.route.params.subscribe(
        (params: Params) => {
            this.user.id = params['id'];
            this.user.name = params['name'];
        }
    );
}
```
* If we add our own observer --> we need to unsubscribe via onDistroy (on course)

Query parameters, Fragment (Pass & retrieve)
-
`localhost:4200/users/1/Max?mode=editing#loading`
Route to an edit page and decide if allowed
### Pass
```typescript
    { path: 'servers/:id/edit', component: EditServerComponent }
```
```htmlmixed
<a
    [routerLink]="['/servers', server.id,'edit']"
    [queryParams]="{allowEdit: '1'}"
    fragment="loading"
    routerLinkActive="active"
    > Edit Server </a> </li>
```
### Retrieve
> app.component.ts
>
```typescript
this.route.snapshot.queryParams;
this.route.queryParams.subscribe();
```
### Nested Router
load menu next to current menu
```typescript=
const appRoutes: Routes =[
    { path: 'servers', component: ServersComponent, children: [
        { path: '/:id', component: ServersComponent }
        { path: '/:id/edit', component: EditServersComponent }
    ] }
]
```
```htmlmixed=
<router-outlet></router-outlet>
// instead of app-servers, app-servers-edit components
```
Wildcard Route
-
For Routes we don't have - 404/Redirect page
```typescript=
{ path: 'page-not-found', component: PageNotFoundComponent }
{ path: '**', redirectTo: '/page-not-found' }
```
`**` always put last in Routes

Cleaner code
-
Creatring a router mdoule and remove routing from app.module
> app.module
```typescript=
import { AppRoutingModule } from './app-routing.module.ts';
imports: [
    AppRoutingModule
]
```
> app-routing.module.ts
```typescript=
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

import {HomeComponent } from '/home/home.component';
// import all Components
 
const appRoutes: Routes =[
    { path: '', component: HomeComponent }
    { path: 'users', component: UsersComponent }
    { path: 'servers', component: ServersComponent }
]

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

Guards
-
Enables access to routes only for logined users
> auth-guard.service.ts
(dont forget importing to `app.module.ts`)
```typescript=
import {
    CanActivate,
    ActivatedRouterSnapshot,
    RouterStateSanpshot } from `@angular/core`;
import { AuthService } from './auth.service';

@Injectable()
export class AuthGuard implements CanActivate, CanActivateChild {
    constructor(
        private authService: AuthService
        private router: Router) {}
    
    canActivate(route: ActivateRouteSnapshot,
                state: RouterStateSnapshot):
                    Observable<boolean> | Promise<boolean> | boolean {
        return his.authService.isAuthenticated().then(
            (authenticated: boolen) => {
                if (authenticated)
                    return true;
                else
                    this.router.navigate(['/']);
                    // navigate home or just return false
            });
    }
    
    // To guard only the childs of this route
    canActivateChild(route: ActivateRouteSnapshot,
                    state: RouterStateSnapshot):
                    Observable<boolean> | Promise<boolean> | boolean {
        return this.canActivate(route,state);
}
```
> auth.service.ts (dummy service - in realworld, here we access the server)
```typescript=
export class AuthService {
    loggedIn = false;

    isAuthenticated() {
        const promise = new Promise(
            (resolve, reject) => {
                setTimeout( () => {
                    resolve(this.loggedIn);
                }, 800); //ms
            }
        );
        return promise;
    }    

    login(){
        this.loggedIn = true;
    }

    logout(){
        this.loggedIn = false;
    }
}
```
> app-routing.module.ts
```typescript=
// Inside the array, enter all guards should be used on this route
{ path: 'users', canActivate: [AuthGuard], component: UsersComponent }
// Guard childs, add this in parent
{ path: 'users', canActivateChild: [AuthGuard], component: UsersComponent }

```

Enable Login with AuthService
-
> home.component.html
```htmlmixed=
<button class="btn btn-default" (click)="onLogin()">
    Login
</button>
<button class="btn btn-default" (click)="onLogout()">
    Logout
</button>
```
> home.component.ts
```typescript=
constructor(... private authService: AuthService) { }

onLogin() {
    this.authService.login();
}

onLogout() {
    this.authService.logout();
}
```
no visual indication yet, but content is now available only for logged in users.

Control wheter you're allowed to leave a Route 
-
like leaving without saving/submitting.
> edit.server.ts
```typescript=
import { Observeable } from 'rxjs/Observable';

export class EditServerComponent implements CanComponentDeactivate {
    allowEdit = false;
    changesSaved = false;

    onUpdateServer(){
        this.changesSaved = true;
    }

    canDeactivate() {
        if (!this.allowEdit)
            return true;
        // onInit we binded serverName with server.name
        // serverName: bound property to input
        // server.name: previous value
        if (this.serverName !== this.server.name ||
            this.serverStatus !== this.server.status &&
           !this.changesSaved)
            return confirm('Do you want to discard changes?');
        else
            return true;
    }
}
   
```
**Add a new File**
> can-deactivate-guard.service.ts
```typescript=
export interface CanComponentDeactivate {
    canDeactivate: () => Observable<boolean> | Promise<boolean> | boolean;
}
//interface, therefore needs to be implmeneted.
export class CanDeactivateGuard implements
    CanDeacivate<CanComponentDeactivate>{
    
        canDeactivate(component: CanComponentDeactivate,
                      currentRoute: ActivatedRouteSnapshot,
                      currentState: RouterStateSnapshot,
                      nextState?: RouterStateSnapshot):
                    // nextState? - Optional argument
            // Function's returned value is the below
            Observable<boolean> | Promise<boolean> | boolean {
        
        return component.canDeactivate();
    }
}
```
> app-routing.module.ts
```typescript=
{ path: 'users', component: UsersComponent,
    canDeactivate: [CanDeactivateGuard]}
```
and don't forget to provide service in `app.module.ts`

Get dynamic data to a Route
-
(Previeus chapter deals with static data)
* Resolver (service) - run some code before the Route is rendered
* Preload some data from the server before accesing/displaying route
* Alternative - Load instantly and present a spinner. 
* Create a new service to retrieve data with a resolver instead of via params.
* Important when using asynchronis data

> server-resolver.service.ts
```typescript=
import { Resolve } from '@angular/router';

interface Server {
    id: number;
    name: string;
    status: string;
}

@Injectable
export class ServerResolver implements Resolve<Server> {
    constructor(private serversService: ServersService)
    resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):
        Observable<Server> | Promise<Server> | Server {
            //'+' - cast to integer
            return this.serversService.getServer(+route.params['id'])
    }
}
```
> app-routing.module.ts
```typescript=
{ path: 'users', component: UsersComponent,
    resolve: {server: ServerResolver} }
```
this will map the data it gives us back
> server.component.ts
```typescript=
ngOnInit() {
    this.route.data.subscribe(
        (data: Data) => {
            this.server = data['server']
        }
    );
}
```
Hash Configuration
-
On real server, the URL is parsed by the web server first, not by angular.
Adding `#` to the URL - `localhost:4200/#/servers`
informs the server to parse only the first part of the URL `localhost:4200/`
and let Angular parse the rest `/servers`
> app-routing.module.ts
```typescript=
imports: [
    RouterModule.forRoot(appRoutes, {useHash: true})
]
```
<!-- <hr> -->
### Avoid reloading the page when clicking on elements
1. Remove `href="#"` - this calls the web server
2. Add
```CSS
style="cursor: pointer;"
```
to view clickable when hovering over the element.
### New item / Edit item page
> recipe-edit.component.ts
```typescript=
export class RecipeEditComponent implements OnInit {
  id: number;
  editMode = false;

  constructor(private route: ActivatedRoute) { }

  ngOnInit() {
    this.route.params
      .subscribe(
        (params: Params) => {
            // retrieve id dynamically
          this.id = +params['id'];
            // if route has id parameter - then we are in Edit mode
            // else: we are creating a New item
          this.editMode = params['id'] != null;
        }
      );
  }
}
```
> app-routing.module.ts
```typescript=
{ path: 'new', component: RecipeEditComponent },
{ path: ':id', component: RecipeDetailComponent },
```
* Must put `new` before `:id` to avoid error - Routing does first match prefix
(`localhost:4200/recipe/new` will fail because `id=new` not identified as valid id)
* Both `New` and `Edit` are handled within same component - can be tell apart by `editMode` property.


___

Observables
=
Observables provide support for passing messages between publishers and subscribers in your application. 
<hr>

#### Observable
Various data sources - events, Http requests, Triggered in code (button)
Passing adata to the observer upon asynchronous events.

#### Observer
Listen to an observable in order to execute our code
* Handle Data
* Handle Error
* Handle Completion - doesn't have to complete (button can be clicked many times)

In Routing, the **Observer** subscribe to changes in Params, Here Angular is emiting the change in URL and deliver the data change to Params.

Subscribe method can get 3 arguments (callbacks): handle data, error and completion.

Create an Observable
-
> component.ts
```typescript=
import { Observable } from 'rxjs/Observable';
import 'rxjs/Rx';
import { Observer } from 'rxjs/Observer';

// The observable is created on init.
// gets a code that is executed right away (OnInit).
ngOnInit() {
    // we will pass string argument to the observer    
    const myObservable = Observable.create((observer: Observer<string>) => {
          setTimeout(() => {
            // next() - pass regular package
            observer.next('first package');
          }, 2000);
          setTimeout(() => {
            // error() - pass error package
            observer.error('this does not work');
          }, 4000);
          setTimeout(() => {
            // complete() - pass event completed
            observer.complete();
          }, 5000);
          setTimeout(() => {
            observer.next('third package');
          }, 6000);
        });
    // The observer is listening to asynchronous events
    // emited by the observable and handles them    
    this.customObsSubscription = myObservable.subscribe(
          (data: string) => { console.log(data); },
          (error: string) => { console.log(error); },
          () => { console.log('completed'); }
        );
}
```

```typescript=
// Infinite observable
const myNumbers = Observable.interval(1000);
myNumbers.subscribe(
    (number: number) => {
        console.log(number);
    }
);
```
This will cause memory leak since there's an active subscription, and it will keep running even after leaving home.component (destroyed)

Therefore we should unsubscribe onDestroy
```typescript=
export class HomeComponent implements OnInit, OnDestroy {
    numbersObsSubscription : Subscription;
    
    ngOnInit() {
        const myNumbers = Observable.interval(1000);
        this.numbersObsSubscription = myNumbers.subscribe( (number: number) => {
            console.log(number);
            }
        );
    }
    
    ngOnDestroy() {
        this.numbersObsSubscription.unsubscribe();
    }
}
```
#### Many ways to create Observables
RxJs Documentation - ReactiveX.io/rxjs/
(We only used `create()` and `inverval()`)

### Subject
Observer & Observable in one convenient object.
Alternative to `emit` when communicating between compoenents
* `new Subject()` instead of `new EventEmitter()`
* `next()` instead of `emit()`
* must be unsubscribed when destroyed

Allows you to push it to emit new data during your code
> users.service.ts
```typescript=
import { Subject } from 'rxjs/Subject';

export class UsersService {
    // Creating the Observable
    userActivated = new Subject();
}
```
> user.component.ts
```typescript=
// this function is executed on button click
// inside user.component.html, which then passes
// a data package to the observer
onActivated() {
    this.usersService.userActivated.next();
}
```
> app.component.ts
```typescript=
export class AppComponent implements OnInit {
    user1Activated = false;
    user2Activated = false;

    constructor(private usersService: UsersService) { }

    ngOnInit() {
        this.usersService.userActivated.subscribe(
            (id: number) => {
                if (id === 1)
                    this.user1Activated = true;
                if (id === 2)
                    this.user2Activated = true;
            }
        );
    }
}
```

Observable Operators
-
Allows you to transform the data you recieve and stay indise the observable
```typescript=
// Here we change the data we get from the interval
// therefore, we pass a tranformation of it.
const myNumbers = Observable.interval(1000)
    .map(
        (data: number) => {
          return data * 2;
        }
      );
myNumbers.subscribe(
    (number: number) => {
        console.log(number);
    }
);
```

___

Forms
=
Better way to handle data input from user (than local reference)

Template-Driven
-
* Angular creates a Javascript representation of the form, when it detects `<form> </form>`
    >app.module.ts
    ```typescript
    import { FormsModule } from '@angular/forms';
    ```
* ngForm: an object created by angular according to the html element + few properties/directive of the form.
* Angular adds dynamically directives like `ng-dirty / ng-valid / ng-dirty` etc. to this object when the value inside an input element is changed/valid 
* ### Style the input according to the state of this directives.
#### Red Border for invalid value
```css=
input.ng-invalid.ng-touched {
  border: 1px solid red;
}
```

* ### Validators:
    * Template - https://angular.io/api?type=directive
    * Reactive - https://angular.io/docs/ts/latest/api/forms/index/Validators-class.html
* Enable HTML5 validation (by default, Angular disables it). Add the `ngNativeValidate`  to a control in the template.
* `ngModel`:
a. `ngModel` - no binding, just letting Angular know that this input is a control
b. `[ngModel]` - one way binding, to select a default value
c. `[(ngModel)]` - two way binding, to use the dynamic changes.
* #### Radio buttons - only one option can be selected
```typescript
genders = ['male', 'female'];
```
```htmlmixed=
<div class="radio" *ngFor="let gender of genders">
  <label>
    <input
      type="radio"
      name="gender"
      ngModel
      [value]="gender"
      required>
    {{ gender }}
  </label>
```
</div>
* Extract data from a form - to present on submit
Need to add the fields to the component's property and bind to it
* There is an option to `reset()` to object (or specific fields)

> component.ts
```typescript=
// Defining `(onSubmite)` to be triggered whenever the HTML submit element is clicked.
// (its default value was to access the server, but we use angular to react since it is a single page app)
// #f - is the form name to access from `component.ts`
<form (ngSubmit)="onSubmit()" #f="ngForm">
    <div
      id="user-data"
    // ngModelGroup - gives us access to the object's data created by this form
      ngModelGroup="userData"
      #userData="ngModelGroup">
      // `form-group` - to gather few inputs to one component
      <div class="form-group">
        <label for="username">Username</label>
        <input
          type="text"
          id="username"
          class="form-control"
          ngModel
          name="username"
        // required input for the form to be valid 
          required>
      </div>
      <button
        class="btn btn-default"
        type="button"
        (click)="suggestUserName()">Suggest an Username</button>
      <div class="form-group">
        <label for="email">Mail</label>
        <input
          type="email"
          id="email"
          class="form-control"
          ngModel
          name="email"
          required
          email
        // #email - local reference to the email data - to use its properties - valid,thouched
          #email="ngModel">
        // Alert message on invalid value 
        <span class="help-block" *ngIf="!email.valid && email.touched">Please enter a valid email!</span>
      </div>
    </div>
    // Entire form control
    <p *ngIf="!userData.valid && userData.touched">User Data is invalid!</p>
```
### Change the object created by the form
```typescript=
export class AppComponent {
    // @viewChild - Provides a reference to elements or components in the view    
    @ViewChild('f') signupForm: NgForm;

    suggestUserName() {
        const suggestedName = 'Superuser';
        // setValue - pass entire object to be set on the form
        this.signupForm.setValue({
          userData: {
            username: suggestedName,
            email: ''
          },
          secret: 'pet',
          questionAnswer: '',
          gender: 'male'
        });
        // patchValue - set a specific field data
        this.signupForm.form.patchValue({
          userData: {
            username: suggestedName
          }
        });
    }
}
```

Reactive
-

> app.module.ts
```typescript
import { ReactiveFormsModule } from '@angular/forms';
```

> app.component.ts
```typescript=
export class AppComponent implements OnInit {
    genders = ['male', 'female'];
    // Reactive form
    signupForm: FormGroup;
    forbiddenUsernames = ['Chris', 'Anna'];

  constructor() {}

  ngOnInit() {
    // connecting controls to the HTML elements
    this.signupForm = new FormGroup({
      'userData': new FormGroup({
        // Arguments:  1) default value (null)
        //             2) validators (or array of them), passing a reference
        //             3) Async validators
        'username': new FormControl(null,
                            // bind this since we use it in the validator
                    [Validators.required, this.forbiddenNames.bind(this)]),
        'email': new FormControl(null,
                    [Validators.required, Validators.email], this.forbiddenEmails)
      }),
      'gender': new FormControl('male'),
      'hobbies': new FormArray([])
    });
    // this.signupForm.valueChanges.subscribe(
    //   (value) => console.log(value)
    // );
    this.signupForm.statusChanges.subscribe(
      (status) => console.log(status)
    );
    this.signupForm.setValue({
      'userData': {
        'username': 'Max',
        'email': 'max@test.com'
      },
      'gender': 'male',
      'hobbies': []
    });
    this.signupForm.patchValue({
      'userData': {
        'username': 'Anna',
      }
    });
  }

  onSubmit() {
    console.log(this.signupForm);
    this.signupForm.reset();
  }

  onAddHobby() {
    // cast to `FormArray` and push into it
    const control = new FormControl(null, Validators.required);
    (<FormArray>this.signupForm.get('hobbies')).push(control);
  }
  // can be written here or in an external like 'CustomValidators'
  forbiddenNames(control: FormControl): {[s: string]: boolean} {
    if (this.forbiddenUsernames.indexOf(control.value) !== -1) {
      return {'nameIsForbidden': true};
    }
    // by returning null - let Angular know it is valid
    return null;
  }

  forbiddenEmails(control: FormControl): Promise<any> | Observable<any> {
    const promise = new Promise<any>((resolve, reject) => {
      setTimeout(() => {
        if (control.value === 'test@test.com') {
          resolve({'emailIsForbidden': true});
        } else {
          resolve(null);
        }
      }, 1500);
    });
    return promise;
  }
}
```

#### Connecting an HTML element to the typescript control
Control: `formControlName="email"`
Control Group: `formGroupName="userData"`
Control Array: `formArrayName="hobbies"`
> component.html
```htmlmixed=
<form [formGroup]="signupForm" (ngSubmit)="onSubmit()">
        // Reactive: name of parent control (above 'username' & 'email')
        <div formGroupName="userData">
          <div class="form-group">
            <label for="username">Username</label>
            <input
              type="text"
              id="username"
              <!-- connecting this element to the typescript control -->
              formControlName="username"
              class="form-control">
            // get access to a control in the form
             <span
              *ngIf="!signupForm.get('userData.username').valid &&
                     signupForm.get('userData.username').touched"
              class="help-block">
              // Error code
              <span *ngIf="signupForm.get('userData.username').errors
                           ['nameIsForbidden']">This name is invalid!</span>
              <span *ngIf="signupForm.get('userData.username').errors
                           ['required']">This field is required!</span>
            </span>
          </div>
          <div class="form-group">
            <label for="email">email</label>
            <input
              type="text"
              id="email"
              formControlName="email"
              class="form-control">
            <span
              *ngIf="!signupForm.get('userData.email').valid && signupForm.get('userData.email').touched"
              class="help-block">Please enter a valid email!</span>
          </div>
        </div>
        <div class="radio" *ngFor="let gender of genders">
          <label>
            <input
              type="radio"
              formControlName="gender"
              [value]="gender">{{ gender }}
          </label>
        </div>
        <div formArrayName="hobbies">
          <h4>Your Hobbies</h4>
          // Button to add a control to the form
          <button
            class="btn btn-default"
            type="button"
            (click)="onAddHobby()">Add Hobby</button>
          <div
            class="form-group"
            *ngFor="let hobbyControl of signupForm.get('hobbies').controls; let i = index">
            <input type="text" class="form-control" [formControlName]="i">
          </div>
        </div>
        <span
          *ngIf="!signupForm.valid && signupForm.touched"
          class="help-block">Please enter valid data!</span>
        <button class="btn btn-primary" type="submit">Submit</button>
      </form>
```
#### Validator for an integer (built in)
```htmlmixed
// property binding short way
pattern="^[1-9]+[0-9]*$"
```
#### On edit mode
* Populate selected item data to the form's fields (video #208)
* Change 'Add' button to 'Update'
```htmlmixed
<button> {{ editMode ? 'Update' : 'Add'}} </button>
```


___

Http & Authentication
=
<hr>
Http
=
* Requests to do some calculation on the server
* Access the database must reload the app
* Http is a solution that keeps our app a SPA

#### Create a service to deal with Http 
> server.service.ts
```typescript=
import { Injectable } from '@angular/core';
import { Headers, Http, Response } from '@angular/http';
import 'rxjs/Rx';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class ServerService {
  constructor(private http: Http) {}
    
  storeServers(servers: any[]) {
    //  Adding Header to an Http request
    const headers = new Headers({'Content-Type': 'application/json'});
    //  This link is for the file in the database
    return this.http.put('https://udemy-ng-http.firebaseio.com/data.json',
      servers,
      {headers: headers});
  }
    
  getServers() {
    return this.http.get('https://udemy-ng-http.firebaseio.com/data')
      //  `map` - Centerlize the data received from the server
      //          for usage all over the app's components
      //          Does it by wrapping it with an Observable
      .map(
        (response: Response) => {
          //  Angular automatically turn it to JS object via `response.json()`
          const data = response.json();
          for (const server of data) {
            server.name = 'FETCHED_' + server.name;
          }
          return data;
        }
      )
      // Error Handling - when accessing database (data instead of data.json)
      // Passing an observable like on data get method
      .catch(
        (error: Response) => {
          return Observable.throw('Something went wrong');
        }
      );
  }
  getAppName() {
    return this.http.get('https://udemy-ng-http.firebaseio.com/appName.json')
      .map(
        (response: Response) => {
          return response.json();
        }
      );
  }
}
```
* Usually `POST` appends data to the database and `PUT` overrides it.
```typescript 
return this.http.post('https://udemy-ng-http.firebaseio.com/data.json',
    servers,
    {headers: headers});
```
* Angular threat this requests with Observables
* ` extract the data from json file to JS object
> app.component.ts
```typescript=
import { Component } from '@angular/core';
import { Response } from '@angular/http';

import { ServerService } from './server.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  appName = this.serverService.getAppName();
  servers = [
    {
      name: 'Testserver',
      capacity: 10,
      id: this.generateId()
    }
  ];

  constructor(private serverService: ServerService) {}

  onAddServer(name: string) {
    this.servers.push({
      name: name,
      capacity: 50,
      id: this.generateId()
    });
  }

  // Http response data handling (App usage)
  onSave() {
    this.serverService.storeServers(this.servers)
      .subscribe(
        (response) => console.log(response),
        (error) => console.log(error)
      );
  }

  onGet() {
    this.serverService.getServers()
      .subscribe(
        (servers: any[]) => this.servers = servers,
        (error) => console.log(error)
      );
  }
}

```
<hr>
Authentication
=
On SPA there's no open session between client and server.
Instead, the server send a token for the client to attach on future requests.
* JWT - JSON Web Token
https://jwt.io/introduction/

### Create SignIn/SignOut pages
1. App should initialized the connection to the backend
* Install firebase (for using it's SDK and libraries)
`ng install --save firebase`
> app.component.ts
```typescript=
import * as firebase from 'firebase';

ngOnInit() {
    firebase.initializeApp({
      apiKey: "AIzaSyDGDTtGNC4FkKpSe85qb2wLHzNi2xkxFy8",
      authDomain: "ng-recipe-book.firebaseapp.com"
    });
}
```

2. Create a service to handle authentication with FireBase SDK
> auth.service.ts
```typescript=
import { Router } from '@angular/router';
import * as firebase from 'firebase';
import { Injectable } from '@angular/core';

@Injectable()
export class AuthService {
  token: string;

  constructor(private router: Router) {}

  signupUser(email: string, password: string) {
    firebase.auth().createUserWithEmailAndPassword(email, password)
      .catch(
        error => console.log(error)
      )
  }

  // On SignIn, save the token received for future requests
  signinUser(email: string, password: string) {
    firebase.auth().signInWithEmailAndPassword(email, password)
      .then(
        response => {
          this.router.navigate(['/']);
          firebase.auth().currentUser.getToken()
            .then(
              (token: string) => this.token = token
            )
        }
      )
      .catch(
        error => console.log(error)
      );
  }

  logout() {
    firebase.auth().signOut();
    this.token = null;
  }

  getToken() {
    firebase.auth().currentUser.getToken()
      .then(
        (token: string) => this.token = token
      );
    return this.token;
  }

  isAuthenticated() {
    return this.token != null;
  }
}
```
3. Creating the forms
> signup.html
```htmlmixed=
<div class="row">
<!--   Bootstrap classes to adjust form looks   -->
  <div class="col-xs-12 col-sm-10 col-md-8 col-sm-offset-1 col-md-offset-2">
    <form (ngSubmit)="onSignup(f)" #f="ngForm">
      <div class="form-group">
        <label for="email">Mail</label>
        <input type="email" id="email" name="email" ngModel class="form-control">
      </div>
      <div class="form-group">
        <label for="password">Password</label>
        <input
          type="password"
          id="password"
          name="password"
          ngModel
          class="form-control">
      </div>
      <button class="btn btn-primary" type="submit" [disabled]="!f.valid">Sign Up</button>
    </form>
  </div>
</div>
```
> signup.ts
```typescript=
export class SignupComponent implements OnInit {

  constructor(private authService: AuthService) { }

  ngOnInit() {}

  onSignup(form: NgForm) {
    const email = form.value.email;
    const password = form.value.password;
    this.authService.signupUser(email, password);
  }
}
```
4. Use the authentication to access data
* Verify Backend read & write guard (mandatory token)
* Use the token when calling get/set.
> data-storage.ts
```typescript
storeRecipes() {
    const token = this.authService.getToken();

    return this.http.put('https://ng-recipe-book.firebaseio.com/recipes.json?auth='
                         + token, this.recipeService.getRecipes());
}
```
5. Creating Auth-Guard to prevent accessing a route while not authenticated
* Create the below guard and then add it to the Routes table on 'app.module'
> auth-guard.ts
```typescript=
import { CanActivate, 
         ActivatedRouteSnapshot, 
         RouterStateSnapshot } from '@angular/router';
import { Injectable } from '@angular/core';
import { AuthService } from './auth.service';

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(private authService: AuthService) {}

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    return this.authService.isAuthenticated();
  }
}
```

___

