Angular Summary

    npm uninstall -g @angular/cli
    npm i -g @angular/cli
    ng --version
  
  1. Project First Steps
    1. New Angular Project
        ng new my-app
        cd my-app
        ng serve --open
      
        Open in the Browser http://localhost:4200/
      
    2. Install Bootstrap
        cd my-app
        npm i bootstrap
                  Optional: 
                    npm i jquery popper.js
      
    3. Font Awesome
      •   ng add @fortawesome/angular-fontawesome
          Use down arrow and space to select all free options
        
          It updates automatically app.module.ts
        
      • ts file
          import { faTimes } from '@fortawesome/free-solid-svg-icons';
        
          export class TaskItemComponent implements OnInit {
        
            faTimes = faTimes;
            
          }  
        
      • html file
          <div>
            <fa-icon [ngStyle]="{'color': 'red'}" [icon]="faTimes"></fa-icon>
          </div>  
        

    4. Font Awesome - the old way
        cd my-app
        npm i @fortawesome/fontawesome-free
      
      • Add to the project
        • Way 1:

          In style.css write

                @import "@fortawesome/fontawesome-free/css/all.min.css";
                @import "bootstrap/dist/css/bootstrap.min.css";
                              

        • Way 2:

          Update angular.json file.

                      
                    "styles": [
                      "src/styles.css",
                      "./node_modules/@fortawesome/fontawesome-free/css/all.min.css",
                      "./node_modules/bootstrap/dist/css/bootstrap.min.css"
                    ],
                  
                    --- optional: ---
                    "scripts": [
                      "./node_modules/jquery/dist/jquery.js",
                      "./node_modules/popper.js/dist/umd/popper.js",
                      "./node_modules/bootstrap/dist/js/bootstrap.js"
                    ]            
                  

    5. Create new component
        ng generate component components/layout/header
        ng generate component components/common/button
      
        In older version:
          ng g c components/list --skipTests true
          ng g c components/list-item --skipTests true
      


  2. Global style in src/styles.css

    Put all global styles in this file.


  3. List Of Items

  4. Steps To Create A Service
    1. Create a service
        ng g s services/users --skipTests=true
      
    2. In app.module.ts
        import { HttpClientModule } from '@angular/common/http';  
        import { UsersService } from './services/users.service';
        ...
        imports: [
          ...
          HttpClientModule
        ],  
        ...
        providers: [UsersService],
      
    3. services/users.service.ts
        import { Injectable } from '@angular/core';
        import { HttpClient, HttpHeaders } from '@angular/common/http';
        import { Observable } from 'rxjs';
        
        import { User } from '../models/User';
        
        const httpOptions = {
          headers: new HttpHeaders({
            'Content-Type': 'application/json'
          })
        }
        
            -- OR --
      
            const httpOptions = {
              headers: new HttpHeaders({
                'Content-Type': 'application/json'
              }),
              withCredentials: true
            };
            -----
      
        @Injectable({
          providedIn: 'root'
        })
        export class UsersService {
          rootUrl:string = 'https://jsonplaceholder.typicode.com/users';
        
          constructor(private http:HttpClient) { }
        
          getUsers():Observable<User[]> {
            return this.http.get<User[]>(this.rootUrl);
          }
      
          //////////////
      
          addComment(comment: Comment): Observable {
            return this.http.post(this.rootUrl, comment, httpOptions);
          }
        
          updateComment(comment: Comment): Observable {
            const currUrl: string = `${this.rootUrl}/${comment._id}`;
        
            return this.http.put(currUrl, comment, httpOptions);
          }
        
          deleteComment(_id: string):Observable {
            const currUrl: string = `${this.rootUrl}/${_id}`;
            
            return this.http.delete(currUrl);
          } 
        } 
      

      Explanation
    1. Create a new file /service/data.service.ts
    2. Import @Injectable and create class
    3. Add as a provider to @NgModule
    4. Call from component

  5. Steps To Use A Service #1

  6. Service with Mock data

  7. Communication Between Components

  8. Forms

  9. Events

  10. Template Syntax

  11. Property Binding

  12. Class Biding

  13. ngClass

  14. Style
      <div [style.height.rem]="2"><p>AAA</p></div>
    

  15. Style Binding
      <div [style.border-color]="user.isActive ? 'green' : ''"></div>
    

  16. ngStyle
      <p [ngStyle]="{'color': 'red'}">BBBB</p>
    

      <button [ngStyle]="{ 'background-color': color }" class="btn" (click)="onClick()">
        {{ text }}
      </button>
    

  17. ngStyle

  18. Mouse Events

  19. Pipes

  20. Function with agrument of different types
      removePost(post: Post | number): Observable<Post> {
        const id = typeof post === 'number' ? post : post.id;
        ...
      }
    

  21. Router
    1. Generate Module
        ng g m app-routing
      
    2. Update app.module.ts
        import { AppRoutingModule } from './app-routing/app-routing.module';
      
        imports: [
          ...
          AppRoutingModule
        ],  
      
    3. Update app.component.html
        <div class="container">
          <router-outlet></router-outlet>
        </div>  
      
    4. Update app-routing.module.ts
        import { NgModule } from '@angular/core';
        import { Routes, RouterModule } from '@angular/router';
        
        import { HomeComponent } from '../components/home/home.component';
        import { UsersComponent } from '../components/users/users.component';
        
        const routes: Routes = [
          {path: '', component: HomeComponent},
          {path: 'users', component: UsersComponent},
        ];
        
        @NgModule({
          imports: [RouterModule.forRoot(routes)],
          exports: [RouterModule]
        })
        export class AppRoutingModule { }      
      

        Use when Page Not Found does not work in Angular:
        imports: [RouterModule.forRoot(routes, {useHash: true})]
      

    5. Create components/home.component.html
        <button class="btn btn-secondary" routerLink="/users">Users Section</button>
      
    6. Redirect
        import { Router } from '@angular/router';
      
        constructor(
          private router: Router
        ) { }
      
        myFunc() {
          this.router.navigate(['/somewhere']);  
        }
      

  22. Navbar
      <nav class="navbar navbar-expand navbar-dark bg-success mb-4">
        <div class="container">
          <a routerLink="/" class="navbar-brand">Tasks App</a>
          <div>
            <ul class="navbar-nav ml-auto">
              <li class="nav-item" [routerLinkActive]="['active']" [routerLinkActiveOptions]="{exact: true}">
                <a routerLink="/" class="nav-link">Home</a>
              </li>
              <li class="nav-item" [routerLinkActive]="['active']" [routerLinkActiveOptions]="{exact: true}">
                <a routerLink="/add-task" class="nav-link">Add Task</a>
              </li>
            </ul>
          </div>
        </div>  
      </nav>
    


  23. Creating new module

  24. Auth Module Example

  25. Adding new module with lazy loading

    1. Example #1

      1. Generate a new module and and a new component
          ng g m modules/Account --routing   <----- Make this module ready for navigation
        
          ng g c modules/Account/components/AccountHome --skipTests true
        
      2. In account-routing.module.ts file
          import { AccountHomeComponent } from './components/account-home/account-home.component';
        
          const routes: Routes = [
            { path: '', component: AccountHomeComponent }
          ];
        
      3. In app-routing.module.ts
          const routes: Routes = [
            // --> Lazy Loading
            { path: 'account', 
              loadChildren: () => 
                import('./modules/account/account.module').then(m => m.AccountModule) 
            }
            // <-- Lazy Loading
          ];
        
      4. In navbar
          <a routerLink="/account">Account</a>
        
      5. See project #194

    2. Exapmle #2

      1. Generate a new module
          ng g m views --routing     <----- Make this module ready for navigation
        
      2. Add a link to the navbar in the app.component.html
          <a routerLink="/views" routerLinkActive="active">
            Views
          </a>
        
      3. Add lazy load of the views module in app-routing.module.ts
          const routes: Routes = [
          // --> Lazy Loading
          ...
          {
            path: 'views',
            loadChildren: () => 
              import('./views/views.module').then(m => m.ViewsModule)
          },
          // <-- Lazy Loading
          { path: '', component: HomeComponent },
          { path: '**', component: NotFoundComponent }
        ];
        
      4. Generate a ViewsHome component in the the views module
          ng g c views/components/viewsHome --skipTests true
        
      5. Add a rule in views-routing.module.ts to show ViewsHome component
          const routes: Routes = [  
            { path: '', component: ViewsHomeComponent }
          ];
        
      6. Generate statistics component in the the views module
          ng g c views/components/statistics --skipTests true
        
      7. Show statistics component in ViewsHome component: in views-home-component.html
          <app-statistics></app-statistics>
        
      8. Add usage of Shared module
        • In views.module.ts
            imports: [
              SharedModule
            ]
          
        • Use it in views-home-component.html

    3. Using json info

      Add in tsconfig.app.json file:

        "compilerOptions": {
          ...
          "resolveJsonModule": true,
          "esModuleInterop": true    
        },
      

      See project #149


    4. Nice CSS

        • In .css file
            :host:not(:first-of-type) {   <-- host component, but not the first one 
              display: block;
              margin-top: 20px;
            }
          
        • In .html file
            <app-devider>First Component</app-devider>
            <app-devider>Second Component</app-devider>
          

    5. RxJS
      •             this.myService.getValues()   <--- observable == sourse of event. Observable emits an event
                    .pipe(                       <--- contains a chain of specific operators
                      map(event => console.log(event))   <-- gets an event that is comming out of the observable
                    )
                    .subscribe()
                  
                    ---------------
                  
                    this.myService.getValues()   
                    .pipe(                       
                      map(event => event.someValue),  <-- result of event.someValue is returned automatically
                      map(value => parseInt(value)),  <--   the "value" was return during the previous step
                      map(value => {
                        if (isNaN(value)) {
                          throw new Error('Enter a number')
                        } 
                        return value;
                      })
                    )
                    .subscribe()
                  
                    ---------------  
                  
                    this.myService.getValues()   
                    .pipe(                       
                      map(event => event.someValue),  <-- result of event.someValue is returned automatically
                      map(value => parseInt(value)),  <--   the "value" was return during the previous step
                      map(value => {
                        if (isNaN(value)) {
                          throw new Error('Enter a number')
                        } 
                        return value;
                      })
                    )
                    .subscribe({     <--- observer is inside the subscribe method
                      next(value) {
                        console.log(`Your value is ${value}`);
                      },
                      error(err) {       // catches errors
                        console.error(err.message);
                      },
                      complete() {
                  
                      }
                    })
                  
      • pluck operator
          { color: 'red', year: 2000 }
          -->
          pluck('year')
          -->
          2000
        
          this.myService.getValues()   
          .pipe(
            pluck('target', 'value'),    <-- if input is { target: { value: 'fvhg'}}                       
            map(value => parseInt(value)),  <--   the "value" was return during 
            .....
          )
        
      • observable.subsribe - way 1
          const observable = new Observable((subscriber) => {
            // Throw the value 1 into our pipeline
            subscriber.next(1);
        
            // Marks the observable as complete, no more values will come out
            subscriber.complete();
        
            //Emit an error, no more values will come out. Since complete() was called above, error will not be emitted
            subscriber.error(new Error('hgfhkfvk')); // not throw new Error
          }).pipe(
             // the value 1 will come here
          );
        
        
          observable.subscribe({    <--- observer
            next(value) {
              console.log('Got a value: ', value);
            },
        
            complete() {  // called at complete above, no argument here
              console.log('Observable is complete. Don't expect any values);
            },
        
            error(err) {   // called when error emits
              console.log(err.message);
            }
          });
        
      • observable.subsribe - way 2
          observable.subsribe(
            (value) => console.log('Next value:', value),  // next
            (err) => console.error(err.message),  // error
            () => console.log('COMPLETE')         // completion
          );
        
      • observable.subsribe - way 3
          observable.subsribe(
            (value) => console.log('Next value:', value),  // next
          );
        
      •   const observable = new Observable((subscriber) => {
            // Throw the value 1 into our pipeline
            subscriber.next(1);
            subscriber.next(2);
            subscriber.next(3);
        
            // Marks the observable as complete, no more values will come out
            subscriber.complete();
        
            //Emit an error, no more values will come out. Since complete() was called above, error will not be emitted
            subscriber.error(new Error('hgfhkfvk')); // not throw new Error
          }).pipe(
             // the value 1 will come here
        
              tap(value => console.log('From tap:', value))  // tap - Perform a side effect for every emission on the source Observable, but return an Observable that is identical to the source.    
          );
        
          observable.subsribe(
            (value) => console.log('Next value:', value),  // next
            (err) => console.error(err.message),  // error
            () => console.log('COMPLETE')         // completion
          );
        
          observable.subsribe((value) => {
            console.log('From second subscribe', value);
          });
        

    6. Tools
      • Augury - Chrome Extension

    7. Build
        ng build --prod --base-href .