infuerno.github.io

Pluralsight: Angular Getting Started

References

Introduction

Components in the example application

Sample Architecture

First Things First

References

Building and running the initial application

Modules

ES 2015 Modules

Angular Modules

ES Modules Angular Modules
Code files that import or export something Code files that organise the application into cohesive blocks of functionality
Organise our code files Organise our application
Modularise our code Modularise our application
Promote code reuse Promote application boundaries

Introduction to Components

What is a component? Creating a component class. Defining metadata with a decorator. Importing dependencies. Bootstrap the app component.

@Component({
  selector: 'pm-root', // Directive Name (simply a custom HTML tag)
  template: `<div><h1></h1></div>`
})

This a function (hence ()) which is passed an anonymous object (hence {})

import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { AppComponent } from "./app-component";

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

Templates, Interpolation and Directives

for … of vs for … in

Hence *ngFor uses for .. of

Data Binding & Pipes

Interpolation

Property Binding

Event Binding

Two-way Binding

Pipes

More on Components

Interfaces

Component styles

Component lifecycle

Custom Pipes

@Pipe({
  name: 'convertToSpaces'
})
export class ConvertToSpacesPipe implements PipeTransform {
  transform(value: string, character: string): string {
    return value.replace(character, ' ');
  }
}

Filtering

performFilter(filterBy: string): IProduct[] {
  filterBy = filterBy.ToLocaleLowerCase();
  return this.products.filter((product: IProduct) =>
  product.name.ToLocaleLowerCase().indexOf(filterBy) !== -1);
}

See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

Building Nested Components

Building a Nested Component

Input using Star component

Output

Services and Dependency Injection

Retrieving Data Using HTTP

Observables

Reactive extensions (RxJS) represent a data sequence as an observable sequence, “an observable”.

const source$: Observable<number> = range(0,10); // sample of data
source$.pipe(
  map(x => x * 3),
  filter(x => x % 2 == 0)
).subscribe(x => console.log(x));

Promise vs Observable

Promise Observable
Provides a single future value Emits multiple values over time
Lazy Not lazy
Not cancellable Cancellable - by unsubscribing
- Supports map, filter, reduce and similar operators

Exception Handling

Many things can go wrong when communicating with a backend service e.g. invalid request, lost connection. Two observable operators to help with exception handling are tap and catchError

getProducts(): Observable<IProduct[]> {
  return this.http.get<IProduct[]>(this.productUrl).pipe(
    tap(data => console.log('All: ' + JSON.stringify(data))),
    catchError(this.handleError)
  );
}

private handleError(err: HttpErrorResponse) {
 ... // log to remote logging; throw to calling code etc
 let errorMessage = '';
 if (err.error instanceOf ErrorEvent) {
   errorMessage = `An error occurred: ${err.error.message}`;
 } else {
   errorMessage = `Server return code: ${err.status}, error message is: ${err.message}`;
 }
 console.log(errorMessage);
 return throwError(() => errorMessage);
}

Subscribing to an Observable

this.productService.getProducts().subscribe({
  next: p => this.products = p,
  error: err => this.errorMessage = err
});
ngOnDestroy(): void {
  this.sub && this.sub.unsubscribe();
}

Navigation and Routing Basics

[
  { path: 'products',  component: ProductListComponent },
  { path: 'products/:id', component: ProductDetailComponent },
  { path: 'welcome', component: WelcomeComponent },
  { path: '', redirectTo: 'welcome', pathMatch: 'full' },
  { path: '**', component: PageNotFoundComponent } // no other routes match
]

Configuring routes

  1. Set up a base tag in the index.html e.g. <base href="/">
  2. Add the RouterModule in the root app module
  3. Configure routes on the import by calling RouterModule.forRoot([]) and passing in the list of routes
  4. Add a menu and use routerLink directives bound to template expressions returning link parameter arrays e.g. <a [routerLink]="['/welcome']">Home</a> - the first element is the route, can also add optional route params
  1. Add the <router-outlet></router-outlet> directive to the host component template
  2. Can remove “selectors” for routed components (only required for nested components)

Navigation and Routing Additional Techniques

Handling nulls or undefined

Either use ngIf in the template e.g. *ngIf="product" OR just use the ? safe navigation operator

Guards

Angular Modules

Bootstrap Array

Declarations Array

Exports Array

Imports Array

Providers Array

Reorganising

Building, Testing, and Deploying with the CLI

The CLI is design to help develop, run tests and deploy the application

ng update

Gives commands to update angular, will temporarily update the ng CLI prior to then analysing the code

ng new

ng serve

The CLI launches a development server and listens on port 4200. Compiler is in watch mode and watches for any changes. Files are bundled into memory and are NOT available on disk. ng serve --help lists all the various options e.g. specify a different port.

ng generate

Uses schematics for code generation. Can generate the following using ng g [initial letter]

ng test / ng e2e

Builds the application, launches the browser and executes the karma test runner. The test runner runs in watch mode. The e2e tests use protractor and also launches the browser.

ng build

Outputs two sets of files for ES5 as well as ES2015. The applications has both sets of files and the browser downloads the appropriate set. Differential loading. The build process creates a dist folder with the actual bundles.

Also need to:

Use ng build. Now the files have a hash as part of the file name - cache busting. By default no map files are generated. Use ng build --help to check out the options. e.g. -base-href to have a different root path.

Final Words