infuerno.github.io

Manning: Angular Development with TypeScript

Resources

Organisation

Chapter 1: Introducing Angular

The main advantage which React and Vue.js have over Angular is that they can be embedded easily within another web app. However this will be answered with the introduction of @angular/elements.

Angular Material is a library of approx 30 UI components. Further components are available in other 3rd party libraries e.g. PrimeNG, Kendo UI, DevExtreme. Can also use Bootstrap.

Introducing the Angular CLI

Assuming you have the latest version of the Angular CLI installed, running ng update will update all dependencies with package.json. See https://update.angular.io for further details on updating angular.

ng serve builds bundles in memory without creating files. The following files are generated (regenerated everytime a file changes):

For each bundle, Angular CLI generates a source map file to allow debugging the original TypeScript, even though the browser will run the generated JavaScript. The size of the vendor.bundle.js in the dev build will be greatly reduced in the production build.

Angular CLI uses Webpack to build the bundles and webpack-dev-server to serve the app. ng serve runs webpack-dev-server. Starting Angular 7, Bazel is an alternative to Webpack.

JIT vs AOT compilation

Angular templates need to be compiled for the browser to understand them. With JIT, the compliation happens once the browser has downloaded all the files (the Angular compiler ngc is in the vendor.bundle.js).

Using JIT compilation in production is discouraged since the templates should be precompiled into JavaScript before the bundles are created (also save having to download the compiler). This is what ahead-of-time (AOT) compilation is about.

When bundles are built with the --prod option, Angular CLI performs code optimisation and AOT compilation. See it in action by running ng serve --prod. If third party libraries produce AOT errors, it can be turned off: ng serve --prod --aot false.

Whereas ng serve generates files in memory, the ng build command generates files in the dist directory (by default), but the bundle sizes won’t be optimized.

With ng build --prod, the generated files will be optimized but not compressed. Gzip compression will need to be applied afterwards.

Chapter 2: The main artefacts of an Angular app

Components

The main artefact - a class with a view (UI). To turn a class into a component, decorate it with the @Component() decorator. (These are Typescript decorators which are processed by the Angular compiler to add additional functionality. Similarity with @Input().)

Services

Services are for code which fetches or manipulates data, for business logic.

Directives

Pipes

A pipe | is a template element to transform output e.g. <p>Your birthday is {{ birthday | date }}</p>

Modules

Container for a group of related components, services, directives and pipes e.g. for shipping or billing

Data binding

Keeps a component’s properties in sync with the view

Chapter 3: Router basics

The <router-outlet> represents the content area used by the router - can have more than one (Chapter 4).

Configuration

const routes: Routes = [
    { path: '', component: HomeComponent },
    { path: 'product', component: ProductDetailComponent }
];

Passing data to routes

Passing query parameters to routes

Child routes

The children property of Route is used to specify relative routes for child components e.g.

const routes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'product/:id', component: ProductDetailComponent,
    children: [
      { path: '', component: ProductDescriptionComponent },
      { path: 'seller/:id', component: SellerInfoComponent }
    ]
  }
];

In this example, there are two <router-outlet>s:

  1. In the app.component.html
  2. In the product.detail.component.html

Two router outlets

:host

:host is a psuedo class selector which can be used with elements created using Shadow DOM (provides better encapsulation for components). Use :host to apply a background colour to the whole component e.g. :host { background: yellow; }

Deep linking

Although the link http://localhost:4200/#/product/1234/seller/5678 works when Angular’s index.html is loaded, it results in a 404 when it isn’t loaded. Any 404s should redirect to index.html so that “deep links” continue to work properly (Angular CLI dev server is already configured to do this).

Router events

There are various events which can be hooked into e.g. NavigationStart and NavigationEnd (see 6.6). For debugging, router events can be logged to the console via the forRoot() method: RouterModule.forRoot(routes, { enableTracing: true })

Chapter 4: Router advanced

Chapter 5: Dependency injection in Angular

Using Angular Material Components

Adding MAT to an Angular app

Chapter 7: Laying out pages with Flex Layout

Using Flex Layout directives

Directive | Description | Values –|– Container directives fxLayout | Use CSS Flexbox to layout children | row, column, row-reverse, column-reverse fxLayout.sm | Specify layout for particular sizes only | Also fxLayout.lt-md for e.g. all breakpoints less than medium fxLayoutAlign | Specify alignment for child elements | either main-axis or cross-axis; start, center, end fxLayoutGap | Controls space between child elements | %, px etc Child directives fxFlex | Controls the amount of space a child takes | %, px, grow, shrink, basis fxFlexAlign | Change the alignment specified with fxLayoutAlign | start, baseline, center, end fxFlexOrder | Change order of elements e.g. move an important component to visible area on smaller screens

MediaObserver service

Subscribe to screen size changes using the MediaObserver service’s media$ observable

export class AppComponent {
  showExtras$: Observable<boolean>;

  constructor(private mediaObserver: MediaObserver) {
    this.showExtras$ = mediaObserver.media$
      .pipe(map(change => {
        return change.mqAlias === 'md' ? true : false;
      }));
  }

Instead of checking the value of mqAlias every time it changes, can instead use isActive API to check if a particular breakpoint is currently active. Ensure the mediaObserver reference is public so that it is accessible in the template. Then simply use e.g. *ngIf="mediaObserver.isActive('md')"

SCSS syntax

Theming

Chapter 14: Testing Angular applications

A unit test should verify that a known, fixed input produces a known, fixed output (Google engineer Elliotte Rusty Harold)

Jasmine is the recommended framework for writing unit tests for Angular applications (there are others). Jasmine comes with its own browser based test runner. Karma is an alternative command line based runner (easier to automate).

Unit test specs are writting BDD style e.g. StarsComponent emits the change rating event (and serves as program documentation). Assertions are followed by matchers e.g. expect(2 + 2).toEqual(4) OR expect(2 + 2).not.toEqual(5). Complete list of matchers are in @types/jasmine/index.d.ts

describe('MyCalculator', () => {                          // A suite description and a function implementing the suite
 it('should know how to multiply', () => { 
   // The code that tests multiplication goes here
});
it('should not divide by zero', () => {                  // A spec to test division
   // The code that tests division by zero goes here
}); });

Appendix A: An overview of ECMAScript

Appendix assumes familiarity with ES5, and only covers enhancements introduced for ES6, 7 and 8.

A2 Scope of variables

Scoping of var is confusing with the variable declaration hoisted to the top of the execution context e.g. function. Use of this is also not straightforward. ES6 solves these problems with the let and const keywords.

A3 Template literals and multiline strings

A4 Optional parameters and default values

As per C#

A5 Arrow function expressions, this and that

Fat arrow functions ensure this behaves properly when you want to access this from a closure (callback function etc).

Reference: http://javascriptissexy.com/understand-javascripts-this-with-clarity-and-master-it/