Renato Ivancic - Software Engineer

Background image

Angular hints

Web Development

Angular

Angular

Angular is a platform that makes it easy to build applications with the web. Angular combines declarative templates, dependency injection, end to end tooling, and integrated best practices to solve development challenges. Angular empowers developers to build applications that live on the web, mobile, or the desktop.

Typescript

TypeScript

TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. Any browser. Any host. Any OS. Open source.

Interfaces

TypeScript (TS) is compiled to JavaScript. JavaScript (JS) does’t have a concept of Interfaces, because inheritance is based on objects not classes and its extremly dynamically typed. You can even undefine all of the the functionality of the object in runtime (Duck typing). Defined Interfaces on classes in TS doesn’t exist at a runtime in JS. Still using them gives us some benefits like strong type checking and TS will throw warnings if used with some tooling.

For example you you dont need to specify implements in class and the Angular application will still invoke onInit() method.

export class CustomComponent {
  ngOnInit() {}
}

But if you provide it you’ll get statical type check and an warning if the ngOnInit() method is not implemented.

TypeScript - Strong typed Interface warning

Pass Async data to child components

Because the application has to be mentainable, remember using components and the principles of encapsulation the Angular application will most likely be build with nested components. Lets say we load product data in a container. Inside the component the call will be made to external service and with the observable the result will arrive some time in the future. But we already pass the parameters in the view to the sub-component. If you want to use the parameter immediately in the constructor or in the onInit method then if the async call did not yet returned the result, bad luck you end up with default or undefined value. Behold there are actually multiple aproaches of how to deal with it:

  • Wrap the template with *ngIf
  • Compute the value in onChange method
  • Use RxJs BehaviorSubject

They are described into details at the scotch.io. I would go with the onChange approach, maybe because I am influenced by the backend development and the golden rule that view model with specific information for concrete view should be used. This means light view with no logic, just presentational structure and style definitions.

RxJS

RxJS

Reactive Extensions Library for JavaScript

RxJS is a library for reactive programming using Observables, to make it easier to compose asynchronous or callback-based code. This project is a rewrite of Reactive-Extensions/RxJS with better performance, better modularity, better debuggable call stacks, while staying mostly backwards compatible, with some breaking changes that reduce the API surface

Upgrade to v6.0

Angular 6.0 uses RxJS 6.0 by default. And it is introducing breaking changes. What happened when we upgraded RxJS in the one project.

I was wondering the whole time what how to properly import and use RxJS components. How that once operator in our code was nested in the pipe() method and another time it is chained to the Observable. Some time the creators are used as stand-alone methods and again in other cases, they are static methods of the Observable itself. My head just started to hurt after all these inconsistencies. Luckily I found a great article from academind.com that shed light on the library version migration. It notes the usage of the rxjs-compat extra library, which makes the library backward compatible. So you can use the library in the new or old way.

From my experiences I strongly discourage usage of the compat library. Let say you have a developer not familiar with the new approach, he will be confused looking at the code. And in the worst case the code will still be written with the compatible version. My suggestion. In the package.json specify only the rxjs 6.0 and remove the compat library. It’s not difficult to upgrade the code base. On a decent project a day with testing should be enough.

Because of the changed project structure:

  • Imports need to be rewritten
  • Pipe operators
  • Some of the operators are renamed (to not clash with the javascript reserved words)

RX Classes and creation methods come from rxjs package.

import { ReplaySubject, Observable, Subscription, combineLatest, merge } from 'rxjs';

All the operators come from rxjs/operators package

import { map, switchMap, tap, debounceTime, distinctUntilChanged, startWith, share, takeUntil, catchError, retry } from 'rxjs/operators';

Example of the rewritten code.


...
import { merge } from 'rxjs';
import { switchMap, catchError } from 'rxjs/operators';
...

private init() {
  this.storesForSelectedRegion$ = merge(
    this.regionsFrom$.pipe(
      switchMap(regions => this.storeService.getStoresForRegion(regions[0].link))
    ),
    this.selectedStoreFromRegion.asObservable().pipe(
      switchMap(regionUrl => this.storeService.getStoresForRegion(regionUrl)),
      catchError(this.handleError('Could not fetch stores for selected region.'))
    )
  );
}

When I repaired the application code I still got similar errors, like the one below:

node_modules/rxjs/BehaviorSubject.d.ts(1,15): error TS2307: Cannot find module 'rxjs-compat/BehaviorSubject'.

It’s because ngx-bootstrap library version was dependend on the older version of RxJS. For this reason it has to updated to the version 3.0, which is compatible with RxJS 6.0

Sources:

Angular.io

Scotch - 3 Ways To Pass Async Data To Angular 2 Child Components

Academind.com - RxJS 6 What Changed

#angular