Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Detecting and solving pain points in Angular Ap...

Detecting and solving pain points in Angular Applications

Starting any Angular Project is easy. AngularCLI provides a great user API, scaffolding is powerful, and the first pages, components are easy to create. But when the application grows, you and your team can run into a lot of problems when developing, architecting and maintaining a single-page application.

Suddenly the architecture gets unmaintainable, dividing the application into logical parts is a challenge and implementing asynchronous operations is hard. Handling the application state and including third party libraries in a proper manner becomes a real challenge. In this talk Fabian Gosebrink shows typical tasks, problems and solutions for mistakes which can be found in Angular applications. We will look at different problems, understand the challenge and develop a solution for common mistakes in Angular solutions so that your next project doesn’t end with "If only somebody told me this before I started my Angular SPA"

Fabian Gosebrink

April 19, 2021
Tweet

More Decks by Fabian Gosebrink

Other Decks in Technology

Transcript

  1. import { NgModule } from '@angular/core'; import { BrowserModule }

    from '@angular/platform-browser'; import { FormsModule } from '@angular/forms'; import { AppComponent } from './app.component'; import { HelloComponent } from './hello.component'; @NgModule({ imports: [ BrowserModule, FormsModule ], declarations: [ AppComponent, HelloComponent ], bootstrap: [AppComponent] }) export class AppModule { } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
  2. import { NgModule } from '@angular/core'; @NgModule({ imports: [ ...

    ], declarations: [ AppComponent, HelloComponent, Hello1Component, Hello2Component, Hello3Component, Hello4Component, Hello5Component, Hello6Component, Hello7Component, Hello8Component, Hello9Component, Hello10Component, Hello11Component, Hello12Component, Hello13Component, Hello14Component, Hello15Component 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
  3. import { NgModule } from '@angular/core'; @NgModule({ imports: [ ...

    ], declarations: [ AppComponent, HelloComponent, Hello1Component, Hello2Component, Hello3Component, Hello4Component, Hello5Component, Hello6Component, Hello7Component, Hello8Component, Hello9Component, Hello10Component, Hello11Component, Hello12Component, Hello13Component, Hello14Component, Hello15Component 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
  4. import { NgModule } from '@angular/core'; @NgModule({ imports: [ ...

    ], declarations: [ AppComponent, Feature1Component1, Feature1Component2, Feature1Component3, Feature1Component4, Feature1Component5, Feature1Component6, Feature2Component1, Feature2Component2, Feature2Component3, Feature2Component4, Feature2Component5, Feature2Component6, ... ], bootstrap: [AppComponent] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
  5. import { NgModule } from '@angular/core'; import { CommonModule }

    from '@angular/common'; @NgModule({ imports: [ CommonModule ], declarations: [ Feature1Component1, Feature1Component2, Feature1Component3, Feature1Component4, Feature1Component5, Feature1Component6, ] }) export class Feature1Module { } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
  6. import { NgModule } from '@angular/core'; import { CommonModule }

    from '@angular/common'; @NgModule({ imports: [ CommonModule ], declarations: [ Feature2Component1, Feature2Component2, Feature2Component3, Feature2Component4, Feature2Component5, Feature2Component6, ] }) export class Feature2Module { } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
  7. import { NgModule } from '@angular/core'; @NgModule({ imports: [ ],

    declarations: [ AppComponent, Feature1Component1, Feature1Component2, Feature1Component3, Feature1Component4, Feature1Component5, Feature1Component6, Feature2Component1, Feature2Component2, Feature2Component3, Feature2Component4, Feature2Component5, Feature2Component6, ], }) export class AppModule { } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
  8. import { NgModule } from '@angular/core'; import { Feature1Module }

    from './feature1-module/feature1.module'; import { Feature2Module } from './feature2-module/feature2.module'; @NgModule({ imports: [ BrowserModule, FormsModule, Feature1Module, Feature2Module ], declarations: [ AppComponent, HelloComponent ], bootstrap: [ AppComponent ] }) export class AppModule { } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
  9. import { NgModule } from '@angular/core'; import { Feature1Module }

    from './feature1-module/feature1.module'; import { Feature2Module } from './feature2-module/feature2.module'; @NgModule({ imports: [ BrowserModule, FormsModule, Feature1Module, Feature2Module ], declarations: [ AppComponent, HelloComponent ], bootstrap: [ AppComponent ] }) export class AppModule { } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import { Feature1Module } from './feature1-module/feature1.module'; import { Feature2Module } from './feature2-module/feature2.module'; Feature1Module, Feature2Module import { NgModule } from '@angular/core'; 1 2 3 4 @NgModule({ 5 imports: [ 6 BrowserModule, 7 FormsModule, 8 9 10 ], 11 declarations: [ 12 AppComponent, 13 HelloComponent 14 ], 15 bootstrap: [ AppComponent ] 16 }) 17 export class AppModule { } 18
  10. import { NgModule } from '@angular/core'; import { CommonModule }

    from '@angular/common'; @NgModule({ imports: [ CommonModule ], declarations: [ Feature2Component1, Feature2Component2, Feature2Component3, Feature2Component4, Feature2Component5, Feature2Component6, ] }) export class Feature2Module { } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
  11. import { NgModule } from '@angular/core'; import { CommonModule }

    from '@angular/common'; @NgModule({ imports: [ CommonModule ], declarations: [ Feature2Component1, Feature2Component2, Feature2Component3, Feature2Component4, Feature2Component5, Feature2Component6, ], exports: [ Feature2Component5, Feature2Component6, ] }) export class Feature2Module { } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
  12. import { NgModule } from '@angular/core'; import { CommonModule }

    from '@angular/common'; @NgModule({ imports: [ CommonModule ], declarations: [ Feature2Component1, // private Feature2Component2, // private Feature2Component3, // private Feature2Component4, // private Feature2Component5, // private Feature2Component6, // private ], exports: [ Feature2Component5, // public Feature2Component6, // public ] }) export class Feature2Module { } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
  13. import { NgModule } from "@angular/core"; import { Feature1Module }

    from "./feature1-module/feature1.modu import { MyComponent } from "./feature1-module/my-component/my.component"; @NgModule({ imports: [ Feature1Module, Feature2Module ], declarations: [ AppComponent, MyComponent // DONT! ], bootstrap: [AppComponent] }) export class AppModule {} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
  14. import { NgModule } from "@angular/core"; import { Feature1Module }

    from "./feature1-module/feature1.modu import { MyComponent } from "./feature1-module/my-component/my.component"; @NgModule({ imports: [ Feature1Module, Feature2Module ], declarations: [ AppComponent, MyComponent // DONT! ], bootstrap: [AppComponent] }) export class AppModule {} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import { MyComponent } from "./feature1-module/my-component/my.component"; MyComponent // DONT! import { NgModule } from "@angular/core"; 1 import { Feature1Module } from "./feature1-module/feature1.modu 2 3 4 5 6 @NgModule({ 7 imports: [ 8 Feature1Module, 9 Feature2Module 10 ], 11 declarations: [ 12 AppComponent, 13 14 ], 15 bootstrap: [AppComponent] 16 }) 17 export class AppModule {} 18
  15. import { NgModule } from "@angular/core"; import { Feature1Module }

    from "./feature1-module/feature1.modu import { MyComponent } from "./feature1-module/my-component/my.component"; @NgModule({ imports: [ Feature1Module, Feature2Module ], declarations: [ AppComponent, MyComponent // DONT! ], bootstrap: [AppComponent] }) export class AppModule {} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import { MyComponent } from "./feature1-module/my-component/my.component"; MyComponent // DONT! import { NgModule } from "@angular/core"; 1 import { Feature1Module } from "./feature1-module/feature1.modu 2 3 4 5 6 @NgModule({ 7 imports: [ 8 Feature1Module, 9 Feature2Module 10 ], 11 declarations: [ 12 AppComponent, 13 14 ], 15 bootstrap: [AppComponent] 16 }) 17 export class AppModule {} 18 import { NgModule } from "@angular/core"; import { Feature1Module } from "./feature1-module/feature1.modu import { MyComponent } from "./feature1-module/my-component/my.component"; @NgModule({ imports: [ Feature1Module, Feature2Module ], declarations: [ AppComponent, MyComponent // DONT! ], bootstrap: [AppComponent] }) export class AppModule {} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
  16. import { NgModule, APP_INITIALIZER, Injectable } from '@angular/core'; import {

    BrowserModule } from '@angular/platform-browser'; import { /* ... */ } from 'lib-to-configure'; import { AppComponent } from './app.component'; export class AppModule {} 1 2 3 4 5 6 7 8
  17. import { NgModule, APP_INITIALIZER, Injectable } from '@angular/core'; import {

    BrowserModule } from '@angular/platform-browser'; import { /* ... */ } from 'lib-to-configure'; import { AppComponent } from './app.component'; export class AppModule {} 1 2 3 4 5 6 7 8 import { NgModule, APP_INITIALIZER, Injectable } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; 1 2 3 import { /* ... */ } from 'lib-to-configure'; 4 5 import { AppComponent } from './app.component'; 6 7 export class AppModule {} 8
  18. import { NgModule, APP_INITIALIZER, Injectable } from '@angular/core'; import {

    BrowserModule } from '@angular/platform-browser'; import { /* ... */ } from 'lib-to-configure'; import { AppComponent } from './app.component'; export class AppModule {} 1 2 3 4 5 6 7 8 import { NgModule, APP_INITIALIZER, Injectable } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; 1 2 3 import { /* ... */ } from 'lib-to-configure'; 4 5 import { AppComponent } from './app.component'; 6 7 export class AppModule {} 8 import { /* ... */ } from 'lib-to-configure'; import { NgModule, APP_INITIALIZER, Injectable } from '@angular/core'; 1 import { BrowserModule } from '@angular/platform-browser'; 2 3 4 5 import { AppComponent } from './app.component'; 6 7 export class AppModule {} 8
  19. import { NgModule, APP_INITIALIZER, Injectable } from '@angular/core'; import {

    BrowserModule } from '@angular/platform-browser'; import { /* ... */ } from 'lib-to-configure'; import { AppComponent } from './app.component'; export class AppModule {} 1 2 3 4 5 6 7 8 import { NgModule, APP_INITIALIZER, Injectable } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; 1 2 3 import { /* ... */ } from 'lib-to-configure'; 4 5 import { AppComponent } from './app.component'; 6 7 export class AppModule {} 8 import { /* ... */ } from 'lib-to-configure'; import { NgModule, APP_INITIALIZER, Injectable } from '@angular/core'; 1 import { BrowserModule } from '@angular/platform-browser'; 2 3 4 5 import { AppComponent } from './app.component'; 6 7 export class AppModule {} 8 import { AppComponent } from './app.component'; import { NgModule, APP_INITIALIZER, Injectable } from '@angular/core'; 1 import { BrowserModule } from '@angular/platform-browser'; 2 3 import { /* ... */ } from 'lib-to-configure'; 4 5 6 7 export class AppModule {} 8
  20. import { NgModule, APP_INITIALIZER, Injectable } from '@angular/core'; import {

    BrowserModule } from '@angular/platform-browser'; import { /* ... */ } from 'lib-to-configure'; import { AppComponent } from './app.component'; export class AppModule {} 1 2 3 4 5 6 7 8 import { NgModule, APP_INITIALIZER, Injectable } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; 1 2 3 import { /* ... */ } from 'lib-to-configure'; 4 5 import { AppComponent } from './app.component'; 6 7 export class AppModule {} 8 import { /* ... */ } from 'lib-to-configure'; import { NgModule, APP_INITIALIZER, Injectable } from '@angular/core'; 1 import { BrowserModule } from '@angular/platform-browser'; 2 3 4 5 import { AppComponent } from './app.component'; 6 7 export class AppModule {} 8 import { AppComponent } from './app.component'; import { NgModule, APP_INITIALIZER, Injectable } from '@angular/core'; 1 import { BrowserModule } from '@angular/platform-browser'; 2 3 import { /* ... */ } from 'lib-to-configure'; 4 5 6 7 export class AppModule {} 8 import { NgModule, APP_INITIALIZER, Injectable } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { /* ... */ } from 'lib-to-configure'; import { AppComponent } from './app.component'; export class AppModule {} 1 2 3 4 5 6 7 8
  21. import { /* ... */ } from './../../../lib-to-configure/src/lib/lib-configuration'; import {

    NgModule, APP_INITIALIZER, Injectable } from '@angular/core'; 1 import { BrowserModule } from '@angular/platform-browser'; 2 3 4 5 import { AppComponent } from './app.component'; 6 7 export class AppModule {} 8
  22. import { /* ... */ } from './../../../lib-to-configure/src/lib/lib-configuration'; import {

    NgModule, APP_INITIALIZER, Injectable } from '@angular/core'; 1 import { BrowserModule } from '@angular/platform-browser'; 2 3 4 5 import { AppComponent } from './app.component'; 6 7 export class AppModule {} 8 Don't
  23. import { /* ... */ } from 'lib-to-configure/public-api'; import {

    NgModule, APP_INITIALIZER, Injectable } from '@angular/core'; 1 import { BrowserModule } from '@angular/platform-browser'; 2 3 4 5 import { AppComponent } from './app.component'; 6 7 export class AppModule {} 8
  24. import { /* ... */ } from 'lib-to-configure/public-api'; import {

    NgModule, APP_INITIALIZER, Injectable } from '@angular/core'; 1 import { BrowserModule } from '@angular/platform-browser'; 2 3 4 5 import { AppComponent } from './app.component'; 6 7 export class AppModule {} 8 import { NgModule, APP_INITIALIZER, Injectable } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { /* ... */ } from 'lib-to-configure/public-api'; import { AppComponent } from './app.component'; export class AppModule {} 1 2 3 4 5 6 7 8
  25. import { /* ... */ } from 'lib-to-configure/public-api'; import {

    NgModule, APP_INITIALIZER, Injectable } from '@angular/core'; 1 import { BrowserModule } from '@angular/platform-browser'; 2 3 4 5 import { AppComponent } from './app.component'; 6 7 export class AppModule {} 8 Don't
  26. import { /* ... */ } from 'lib-to-configure'; import {

    NgModule, APP_INITIALIZER, Injectable } from '@angular/core'; 1 import { BrowserModule } from '@angular/platform-browser'; 2 3 4 5 import { AppComponent } from './app.component'; 6 7 export class AppModule {} 8 Do
  27. import { /* ... */ } from 'lib-to-configure'; import {

    NgModule, APP_INITIALIZER, Injectable } from '@angular/core'; 1 import { BrowserModule } from '@angular/platform-browser'; 2 3 4 5 import { AppComponent } from './app.component'; 6 7 export class AppModule {} 8
  28. import { /* ... */ } from 'lib-to-configure'; import {

    NgModule, APP_INITIALIZER, Injectable } from '@angular/core'; 1 import { BrowserModule } from '@angular/platform-browser'; 2 3 4 5 import { AppComponent } from './app.component'; 6 7 export class AppModule {} 8
  29. @NgModule({ declarations: [LibToConfigureComponent], imports: [CommonModule], exports: [LibToConfigureComponent], }) export class

    LibToConfigureModule {} 1 2 3 4 5 6 @NgModule({ declarations: [AppComponent], imports: [BrowserModule, LibToConfigureModule], providers: [], bootstrap: [AppComponent], }) export class AppModule {} 1 2 3 4 5 6 7
  30. static con g export class LibToConfigureConfiguration { name: string; }

    1 2 3 export * from './lib/lib-configuration'; 1 export * from './lib/lib-to-configure.component'; 2 export * from './lib/lib-to-configure.module'; 3 export * from './lib/lib-to-configure.service'; 4
  31. static con g @NgModule({ /*...*/ }) export class LibToConfigureModule {

    static forRoot( libConfiguration: LibToConfigureConfiguration ): ModuleWithProviders { return { ngModule: LibToConfigureModule, providers: [ { provide: LibToConfigureConfiguration, useValue: libConfiguration, }, ], }; } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
  32. static con g @NgModule({ declarations: [AppComponent], imports: [ BrowserModule, LibToConfigureModule.forRoot({

    name: 'Fabian' }) ], providers: [], bootstrap: [AppComponent], }) export class AppModule {} 1 2 3 4 5 6 7 8 9 10
  33. Dynamic con g @NgModule({ declarations: [AppComponent], imports: [ BrowserModule, LibToConfigureModule.forRoot(

    ??? ) ], providers: [], bootstrap: [AppComponent], }) export class AppModule {} 1 2 3 4 5 6 7 8 9 10
  34. Dynamic con g @NgModule({ declarations: [AppComponent], imports: [ BrowserModule, LibToConfigureModule.forRoot(

    ??? ) ], providers: [ { provide: APP_INITIALIZER, useFactory: appInitializerFn, multi: true, deps: [AppConfigService], }, ], bootstrap: [AppComponent], }) export class AppModule {} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
  35. Dynamic con g export class AppConfigService { private appConfig; constructor(private

    http: HttpClient) { } loadAppConfig() { return this.http.get('/assets/data/appConfig.json') .toPromise() .then(data => { this.appConfig = data; }); } getConfig() { return this.appConfig; } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
  36. Dynamic con g const appInitializerFn = (appConfig: AppConfigService) => {

    return () => { return appConfig.loadAppConfig(); }; }; @NgModule({ declarations: [AppComponent], imports: [ BrowserModule, LibToConfigureModule, HttpClientModule ], providers: [ AppConfigService, { provide: APP_INITIALIZER, useFactory: appInitializerFn, multi: true, deps: [AppConfigService], }, ], bootstrap: [AppComponent], }) export class AppModule {} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
  37. Dynamic con g const appInitializerFn = (appConfig: AppConfigService) => {

    return () => { return appConfig.loadAppConfig(); }; }; @NgModule({ declarations: [AppComponent], imports: [ BrowserModule, LibToConfigureModule, HttpClientModule ], providers: [ AppConfigService, { provide: APP_INITIALIZER, useFactory: appInitializerFn, multi: true, deps: [AppConfigService], }, ], bootstrap: [AppComponent], }) export class AppModule {} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 const appInitializerFn = (appConfig: AppConfigService) => { return () => { return appConfig.loadAppConfig(); }; }; 1 2 3 4 5 6 @NgModule({ 7 declarations: [AppComponent], 8 imports: [ 9 BrowserModule, 10 LibToConfigureModule, 11 HttpClientModule 12 ], 13 providers: [ 14 AppConfigService, 15 { 16 provide: APP_INITIALIZER, 17 useFactory: appInitializerFn, 18 multi: true, 19 deps: [AppConfigService], 20 }, 21 ], 22 bootstrap: [AppComponent], 23 }) 24 export class AppModule {} 25
  38. Dynamic con g const appInitializerFn = (appConfig: AppConfigService) => {

    return () => { return appConfig.loadAppConfig(); }; }; @NgModule({ declarations: [AppComponent], imports: [ BrowserModule, LibToConfigureModule, HttpClientModule ], providers: [ AppConfigService, { provide: APP_INITIALIZER, useFactory: appInitializerFn, multi: true, deps: [AppConfigService], }, ], bootstrap: [AppComponent], }) export class AppModule {} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 const appInitializerFn = (appConfig: AppConfigService) => { return () => { return appConfig.loadAppConfig(); }; }; 1 2 3 4 5 6 @NgModule({ 7 declarations: [AppComponent], 8 imports: [ 9 BrowserModule, 10 LibToConfigureModule, 11 HttpClientModule 12 ], 13 providers: [ 14 AppConfigService, 15 { 16 provide: APP_INITIALIZER, 17 useFactory: appInitializerFn, 18 multi: true, 19 deps: [AppConfigService], 20 }, 21 ], 22 bootstrap: [AppComponent], 23 }) 24 export class AppModule {} 25 useFactory: appInitializerFn, deps: [AppConfigService], const appInitializerFn = (appConfig: AppConfigService) => { 1 return () => { 2 return appConfig.loadAppConfig(); 3 }; 4 }; 5 6 @NgModule({ 7 declarations: [AppComponent], 8 imports: [ 9 BrowserModule, 10 LibToConfigureModule, 11 HttpClientModule 12 ], 13 providers: [ 14 AppConfigService, 15 { 16 provide: APP_INITIALIZER, 17 18 multi: true, 19 20 }, 21 ], 22 bootstrap: [AppComponent], 23 }) 24 export class AppModule {} 25
  39. Dynamic con g LibToConfigureModule.forRoot(???), const appInitializerFn = (appConfig: AppConfigService) =>

    { 1 return () => { 2 return appConfig.loadAppConfig(); 3 }; 4 }; 5 6 @NgModule({ 7 declarations: [AppComponent], 8 imports: [ 9 BrowserModule, 10 11 HttpClientModule 12 ], 13 providers: [ 14 AppConfigService, 15 { 16 provide: APP_INITIALIZER, 17 useFactory: appInitializerFn, 18 multi: true, 19 deps: [AppConfigService], 20 }, 21 ], 22 bootstrap: [AppComponent], 23 }) 24 export class AppModule {} 25
  40. Dynamic con g export class LibToConfigureConfiguration { some: string =

    ''; } export class LibConfiguration { config?: Provider; } @Injectable({ providedIn: 'root' }) export abstract class LibConfigurationProvider { abstract get config(): LibToConfigureConfiguration; } @Injectable({ providedIn: 'root' }) export class DefaultLibConfiguration implements LibConfigurationProvider { get config(): LibToConfigureConfiguration { return { some: `Fallback` }; } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
  41. Dynamic con g export class LibToConfigureConfiguration { some: string =

    ''; } export class LibConfiguration { config?: Provider; } @Injectable({ providedIn: 'root' }) export abstract class LibConfigurationProvider { abstract get config(): LibToConfigureConfiguration; } @Injectable({ providedIn: 'root' }) export class DefaultLibConfiguration implements LibConfigurationProvider { get config(): LibToConfigureConfiguration { return { some: `Fallback` }; } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 export class LibToConfigureConfiguration { some: string = ''; } 1 2 3 4 export class LibConfiguration { 5 config?: Provider; 6 } 7 8 @Injectable({ providedIn: 'root' }) 9 export abstract class LibConfigurationProvider { 10 abstract get config(): LibToConfigureConfiguration; 11 } 12 13 @Injectable({ providedIn: 'root' }) 14 export class DefaultLibConfiguration 15 implements LibConfigurationProvider { 16 17 get config(): LibToConfigureConfiguration { 18 return { some: `Fallback` }; 19 } 20 } 21
  42. Dynamic con g export class LibToConfigureConfiguration { some: string =

    ''; } export class LibConfiguration { config?: Provider; } @Injectable({ providedIn: 'root' }) export abstract class LibConfigurationProvider { abstract get config(): LibToConfigureConfiguration; } @Injectable({ providedIn: 'root' }) export class DefaultLibConfiguration implements LibConfigurationProvider { get config(): LibToConfigureConfiguration { return { some: `Fallback` }; } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 export class LibToConfigureConfiguration { some: string = ''; } 1 2 3 4 export class LibConfiguration { 5 config?: Provider; 6 } 7 8 @Injectable({ providedIn: 'root' }) 9 export abstract class LibConfigurationProvider { 10 abstract get config(): LibToConfigureConfiguration; 11 } 12 13 @Injectable({ providedIn: 'root' }) 14 export class DefaultLibConfiguration 15 implements LibConfigurationProvider { 16 17 get config(): LibToConfigureConfiguration { 18 return { some: `Fallback` }; 19 } 20 } 21 export class LibConfiguration { config?: Provider; } export class LibToConfigureConfiguration { 1 some: string = ''; 2 } 3 4 5 6 7 8 @Injectable({ providedIn: 'root' }) 9 export abstract class LibConfigurationProvider { 10 abstract get config(): LibToConfigureConfiguration; 11 } 12 13 @Injectable({ providedIn: 'root' }) 14 export class DefaultLibConfiguration 15 implements LibConfigurationProvider { 16 17 get config(): LibToConfigureConfiguration { 18 return { some: `Fallback` }; 19 } 20 } 21
  43. Dynamic con g export class LibToConfigureConfiguration { some: string =

    ''; } export class LibConfiguration { config?: Provider; } @Injectable({ providedIn: 'root' }) export abstract class LibConfigurationProvider { abstract get config(): LibToConfigureConfiguration; } @Injectable({ providedIn: 'root' }) export class DefaultLibConfiguration implements LibConfigurationProvider { get config(): LibToConfigureConfiguration { return { some: `Fallback` }; } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 export class LibToConfigureConfiguration { some: string = ''; } 1 2 3 4 export class LibConfiguration { 5 config?: Provider; 6 } 7 8 @Injectable({ providedIn: 'root' }) 9 export abstract class LibConfigurationProvider { 10 abstract get config(): LibToConfigureConfiguration; 11 } 12 13 @Injectable({ providedIn: 'root' }) 14 export class DefaultLibConfiguration 15 implements LibConfigurationProvider { 16 17 get config(): LibToConfigureConfiguration { 18 return { some: `Fallback` }; 19 } 20 } 21 export class LibConfiguration { config?: Provider; } export class LibToConfigureConfiguration { 1 some: string = ''; 2 } 3 4 5 6 7 8 @Injectable({ providedIn: 'root' }) 9 export abstract class LibConfigurationProvider { 10 abstract get config(): LibToConfigureConfiguration; 11 } 12 13 @Injectable({ providedIn: 'root' }) 14 export class DefaultLibConfiguration 15 implements LibConfigurationProvider { 16 17 get config(): LibToConfigureConfiguration { 18 return { some: `Fallback` }; 19 } 20 } 21 @Injectable({ providedIn: 'root' }) export abstract class LibConfigurationProvider { abstract get config(): LibToConfigureConfiguration; } export class LibToConfigureConfiguration { 1 some: string = ''; 2 } 3 4 export class LibConfiguration { 5 config?: Provider; 6 } 7 8 9 10 11 12 13 @Injectable({ providedIn: 'root' }) 14 export class DefaultLibConfiguration 15 implements LibConfigurationProvider { 16 17 get config(): LibToConfigureConfiguration { 18 return { some: `Fallback` }; 19 } 20 } 21
  44. Dynamic con g export class LibToConfigureConfiguration { some: string =

    ''; } export class LibConfiguration { config?: Provider; } @Injectable({ providedIn: 'root' }) export abstract class LibConfigurationProvider { abstract get config(): LibToConfigureConfiguration; } @Injectable({ providedIn: 'root' }) export class DefaultLibConfiguration implements LibConfigurationProvider { get config(): LibToConfigureConfiguration { return { some: `Fallback` }; } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 export class LibToConfigureConfiguration { some: string = ''; } 1 2 3 4 export class LibConfiguration { 5 config?: Provider; 6 } 7 8 @Injectable({ providedIn: 'root' }) 9 export abstract class LibConfigurationProvider { 10 abstract get config(): LibToConfigureConfiguration; 11 } 12 13 @Injectable({ providedIn: 'root' }) 14 export class DefaultLibConfiguration 15 implements LibConfigurationProvider { 16 17 get config(): LibToConfigureConfiguration { 18 return { some: `Fallback` }; 19 } 20 } 21 export class LibConfiguration { config?: Provider; } export class LibToConfigureConfiguration { 1 some: string = ''; 2 } 3 4 5 6 7 8 @Injectable({ providedIn: 'root' }) 9 export abstract class LibConfigurationProvider { 10 abstract get config(): LibToConfigureConfiguration; 11 } 12 13 @Injectable({ providedIn: 'root' }) 14 export class DefaultLibConfiguration 15 implements LibConfigurationProvider { 16 17 get config(): LibToConfigureConfiguration { 18 return { some: `Fallback` }; 19 } 20 } 21 @Injectable({ providedIn: 'root' }) export abstract class LibConfigurationProvider { abstract get config(): LibToConfigureConfiguration; } export class LibToConfigureConfiguration { 1 some: string = ''; 2 } 3 4 export class LibConfiguration { 5 config?: Provider; 6 } 7 8 9 10 11 12 13 @Injectable({ providedIn: 'root' }) 14 export class DefaultLibConfiguration 15 implements LibConfigurationProvider { 16 17 get config(): LibToConfigureConfiguration { 18 return { some: `Fallback` }; 19 } 20 } 21 @Injectable({ providedIn: 'root' }) export class DefaultLibConfiguration implements LibConfigurationProvider { get config(): LibToConfigureConfiguration { return { some: `Fallback` }; } export class LibToConfigureConfiguration { 1 some: string = ''; 2 } 3 4 export class LibConfiguration { 5 config?: Provider; 6 } 7 8 @Injectable({ providedIn: 'root' }) 9 export abstract class LibConfigurationProvider { 10 abstract get config(): LibToConfigureConfiguration; 11 } 12 13 14 15 16 17 18 19 20 } 21
  45. Dynamic con g @NgModule({ /*...*/ }) export class LibToConfigureModule {

    static forRoot( libModuleConfiguration: LibConfiguration = {} ): ModuleWithProviders { return { ngModule: LibToConfigureModule, providers: [ libModuleConfiguration.config || { provide: LibConfigurationProvider, useClass: DefaultLibConfiguration, }, ], }; } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
  46. Dynamic con g @NgModule({ /*...*/ }) export class LibToConfigureModule {

    static forRoot( libModuleConfiguration: LibConfiguration = {} ): ModuleWithProviders { return { ngModule: LibToConfigureModule, providers: [ libModuleConfiguration.config || { provide: LibConfigurationProvider, useClass: DefaultLibConfiguration, }, ], }; } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 libModuleConfiguration: LibConfiguration = {} libModuleConfiguration.config || { @NgModule({ 1 /*...*/ 2 }) 3 export class LibToConfigureModule { 4 static forRoot( 5 6 ): ModuleWithProviders { 7 return { 8 ngModule: LibToConfigureModule, 9 providers: [ 10 11 provide: LibConfigurationProvider, 12 useClass: DefaultLibConfiguration, 13 }, 14 ], 15 }; 16 } 17 } 18
  47. Dynamic con g @NgModule({ /*...*/ }) export class LibToConfigureModule {

    static forRoot( libModuleConfiguration: LibConfiguration = {} ): ModuleWithProviders { return { ngModule: LibToConfigureModule, providers: [ libModuleConfiguration.config || { provide: LibConfigurationProvider, useClass: DefaultLibConfiguration, }, ], }; } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 libModuleConfiguration: LibConfiguration = {} libModuleConfiguration.config || { @NgModule({ 1 /*...*/ 2 }) 3 export class LibToConfigureModule { 4 static forRoot( 5 6 ): ModuleWithProviders { 7 return { 8 ngModule: LibToConfigureModule, 9 providers: [ 10 11 provide: LibConfigurationProvider, 12 useClass: DefaultLibConfiguration, 13 }, 14 ], 15 }; 16 } 17 } 18 provide: LibConfigurationProvider, useClass: DefaultLibConfiguration, @NgModule({ 1 /*...*/ 2 }) 3 export class LibToConfigureModule { 4 static forRoot( 5 libModuleConfiguration: LibConfiguration = {} 6 ): ModuleWithProviders { 7 return { 8 ngModule: LibToConfigureModule, 9 providers: [ 10 libModuleConfiguration.config || { 11 12 13 }, 14 ], 15 }; 16 } 17 } 18
  48. Dynamic con g @Injectable({ providedIn: 'root' }) export class ConfigurationStore

    { private internalConfig: LibToConfigureConfiguration; setConfig(config: LibToConfigureConfiguration) { this.internalConfig = config; } getConfig() { return this.internalConfig; } } @NgModule({ /* .. */ }) export class AppModule {} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
  49. Dynamic con g @Injectable({ providedIn: 'root' }) export class ConfigurationStore

    { private internalConfig: LibToConfigureConfiguration; setConfig(config: LibToConfigureConfiguration) { this.internalConfig = config; } getConfig() { return this.internalConfig; } } @NgModule({ /* .. */ }) export class AppModule {} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Injectable({ providedIn: 'root' }) export class ConfigurationStore { private internalConfig: LibToConfigureConfiguration; setConfig(config: LibToConfigureConfiguration) { this.internalConfig = config; } getConfig() { return this.internalConfig; } } 1 2 3 4 5 6 7 8 9 10 11 12 13 @NgModule({ 14 /* .. */ 15 }) 16 export class AppModule {} 17
  50. Dynamic con g @Injectable({ providedIn: 'root' }) export class ConfigurationStore

    { ... } export function initApp(configurationStore: ConfigurationStore) { return () => { return new Promise<void>((resolve) => { setTimeout(() => { configurationStore.setConfig({ some: 'Fabian' }); resolve(); }, 2000); }); }; } @NgModule({ /* .. */ }) export class AppModule {} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
  51. Dynamic con g @Injectable({ providedIn: 'root' }) export class ConfigurationStore

    { ... } export function initApp(configurationStore: ConfigurationStore) { return () => { return new Promise<void>((resolve) => { setTimeout(() => { configurationStore.setConfig({ some: 'Fabian' }); resolve(); }, 2000); }); }; } @NgModule({ /* .. */ }) export class AppModule {} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 export function initApp(configurationStore: ConfigurationStore) { return () => { return new Promise<void>((resolve) => { setTimeout(() => { configurationStore.setConfig({ some: 'Fabian' }); resolve(); }, 2000); }); }; } @Injectable({ providedIn: 'root' }) 1 export class ConfigurationStore { ... } 2 3 4 5 6 7 8 9 10 11 12 13 14 @NgModule({ 15 /* .. */ 16 }) 17 export class AppModule {} 18
  52. Dynamic con g @Injectable({ providedIn: 'root' }) export class ConfigurationStore

    { ... } export function initApp(configurationStore: ConfigurationStore) { ...} @Injectable({ providedIn: 'root' }) export class ConfigFromApp implements LibConfigurationProvider { constructor(private configStore: ConfigurationStore) {} get config(): LibToConfigureConfiguration { return this.configStore.getConfig(); } } @NgModule({ /* .. */ }) export class AppModule {} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
  53. Dynamic con g @Injectable({ providedIn: 'root' }) export class ConfigurationStore

    { ... } export function initApp(configurationStore: ConfigurationStore) { ...} @Injectable({ providedIn: 'root' }) export class ConfigFromApp implements LibConfigurationProvider { constructor(private configStore: ConfigurationStore) {} get config(): LibToConfigureConfiguration { return this.configStore.getConfig(); } } @NgModule({ /* .. */ }) export class AppModule {} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Injectable({ providedIn: 'root' }) export class ConfigFromApp implements LibConfigurationProvider { constructor(private configStore: ConfigurationStore) {} get config(): LibToConfigureConfiguration { return this.configStore.getConfig(); } } @Injectable({ providedIn: 'root' }) 1 export class ConfigurationStore { ... } 2 3 export function initApp(configurationStore: ConfigurationStore) { ...} 4 5 6 7 8 9 10 11 12 13 14 @NgModule({ 15 /* .. */ 16 }) 17 export class AppModule {} 18
  54. Dynamic con g @Injectable({ providedIn: 'root' }) export class ConfigurationStore

    { ... } export function initApp(configurationStore: ConfigurationStore) { ...} @Injectable({ providedIn: 'root' }) export class ConfigFromApp implements LibConfigurationProvider { ... } @NgModule({ imports: [ LibToConfigureModule.forRoot({ config: { provide: LibConfigurationProvider, useClass: ConfigFromApp, }, }), ], providers: [ { provide: APP_INITIALIZER, useFactory: initApp, multi: true, deps: [ConfigurationStore], }, ], bootstrap: [AppComponent], }) export class AppModule {} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
  55. Dynamic con g @Injectable({ providedIn: 'root' }) export class ConfigurationStore

    { ... } export function initApp(configurationStore: ConfigurationStore) { ...} @Injectable({ providedIn: 'root' }) export class ConfigFromApp implements LibConfigurationProvider { ... } @NgModule({ imports: [ LibToConfigureModule.forRoot({ config: { provide: LibConfigurationProvider, useClass: ConfigFromApp, }, }), ], providers: [ { provide: APP_INITIALIZER, useFactory: initApp, multi: true, deps: [ConfigurationStore], }, ], bootstrap: [AppComponent], }) export class AppModule {} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 LibToConfigureModule.forRoot({ config: { provide: LibConfigurationProvider, useClass: ConfigFromApp, }, }), @Injectable({ providedIn: 'root' }) 1 export class ConfigurationStore { ... } 2 3 export function initApp(configurationStore: ConfigurationStore) { ...} 4 5 @Injectable({ providedIn: 'root' }) 6 export class ConfigFromApp implements LibConfigurationProvider { ... } 7 8 @NgModule({ 9 imports: [ 10 11 12 13 14 15 16 ], 17 providers: [ 18 { 19 provide: APP_INITIALIZER, 20 useFactory: initApp, 21 multi: true, 22 deps: [ConfigurationStore], 23 }, 24 ], 25 bootstrap: [AppComponent], 26 }) 27 export class AppModule {} 28
  56. Dynamic con g @Injectable({ providedIn: 'root' }) export class ConfigurationStore

    { ... } export function initApp(configurationStore: ConfigurationStore) { ...} @Injectable({ providedIn: 'root' }) export class ConfigFromApp implements LibConfigurationProvider { ... } @NgModule({ imports: [ LibToConfigureModule.forRoot({ config: { provide: LibConfigurationProvider, useClass: ConfigFromApp, }, }), ], providers: [ { provide: APP_INITIALIZER, useFactory: initApp, multi: true, deps: [ConfigurationStore], }, ], bootstrap: [AppComponent], }) export class AppModule {} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 LibToConfigureModule.forRoot({ config: { provide: LibConfigurationProvider, useClass: ConfigFromApp, }, }), @Injectable({ providedIn: 'root' }) 1 export class ConfigurationStore { ... } 2 3 export function initApp(configurationStore: ConfigurationStore) { ...} 4 5 @Injectable({ providedIn: 'root' }) 6 export class ConfigFromApp implements LibConfigurationProvider { ... } 7 8 @NgModule({ 9 imports: [ 10 11 12 13 14 15 16 ], 17 providers: [ 18 { 19 provide: APP_INITIALIZER, 20 useFactory: initApp, 21 multi: true, 22 deps: [ConfigurationStore], 23 }, 24 ], 25 bootstrap: [AppComponent], 26 }) 27 export class AppModule {} 28 { provide: APP_INITIALIZER, useFactory: initApp, multi: true, deps: [ConfigurationStore], }, @Injectable({ providedIn: 'root' }) 1 export class ConfigurationStore { ... } 2 3 export function initApp(configurationStore: ConfigurationStore) { ...} 4 5 @Injectable({ providedIn: 'root' }) 6 export class ConfigFromApp implements LibConfigurationProvider { ... } 7 8 @NgModule({ 9 imports: [ 10 LibToConfigureModule.forRoot({ 11 config: { 12 provide: LibConfigurationProvider, 13 useClass: ConfigFromApp, 14 }, 15 }), 16 ], 17 providers: [ 18 19 20 21 22 23 24 ], 25 bootstrap: [AppComponent], 26 }) 27 export class AppModule {} 28
  57. Main.ts import { enableProdMode } from '@angular/core'; import { platformBrowserDynamic

    } from '@angular/platform-browser-dynamic'; import { AppModule } from './app/app.module'; import { environment } from './environments/environment'; if (environment.production) { enableProdMode(); } platformBrowserDynamic() .bootstrapModule(AppModule) .catch((err) => console.error(err)); 1 2 3 4 5 6 7 8 9 10 11 12 https://timdeschryver.dev/blog/angular-build-once-deploy-to-multiple-environments
  58. Main.ts fetch('/assets/config.json') import { enableProdMode } from '@angular/core' 1 import

    { platformBrowserDynamic } from '@angular/platform-browser-dynamic' 2 import { environment } from './environments/environment' 3 import { AppConfig, APP_CONFIG } from './app.config' 4 import { AppModule } from './app/app.module' 5 6 7 .then((response) => response.json()) 8 .then((config) => { 9 if (environment.production) { 10 enableProdMode() 11 } 12 13 platformBrowserDynamic([{ provide: APP_CONFIG, useValue: config }]) 14 .bootstrapModule(AppModule) 15 .catch((err) => console.error(err)) 16 }) 17
  59. Main.ts fetch('/assets/config.json') import { enableProdMode } from '@angular/core' 1 import

    { platformBrowserDynamic } from '@angular/platform-browser-dynamic' 2 import { environment } from './environments/environment' 3 import { AppConfig, APP_CONFIG } from './app.config' 4 import { AppModule } from './app/app.module' 5 6 7 .then((response) => response.json()) 8 .then((config) => { 9 if (environment.production) { 10 enableProdMode() 11 } 12 13 platformBrowserDynamic([{ provide: APP_CONFIG, useValue: config }]) 14 .bootstrapModule(AppModule) 15 .catch((err) => console.error(err)) 16 }) 17 .then((response) => response.json()) import { enableProdMode } from '@angular/core' 1 import { platformBrowserDynamic } from '@angular/platform-browser-dynamic' 2 import { environment } from './environments/environment' 3 import { AppConfig, APP_CONFIG } from './app.config' 4 import { AppModule } from './app/app.module' 5 6 fetch('/assets/config.json') 7 8 .then((config) => { 9 if (environment.production) { 10 enableProdMode() 11 } 12 13 platformBrowserDynamic([{ provide: APP_CONFIG, useValue: config }]) 14 .bootstrapModule(AppModule) 15 .catch((err) => console.error(err)) 16 }) 17
  60. Main.ts fetch('/assets/config.json') import { enableProdMode } from '@angular/core' 1 import

    { platformBrowserDynamic } from '@angular/platform-browser-dynamic' 2 import { environment } from './environments/environment' 3 import { AppConfig, APP_CONFIG } from './app.config' 4 import { AppModule } from './app/app.module' 5 6 7 .then((response) => response.json()) 8 .then((config) => { 9 if (environment.production) { 10 enableProdMode() 11 } 12 13 platformBrowserDynamic([{ provide: APP_CONFIG, useValue: config }]) 14 .bootstrapModule(AppModule) 15 .catch((err) => console.error(err)) 16 }) 17 .then((response) => response.json()) import { enableProdMode } from '@angular/core' 1 import { platformBrowserDynamic } from '@angular/platform-browser-dynamic' 2 import { environment } from './environments/environment' 3 import { AppConfig, APP_CONFIG } from './app.config' 4 import { AppModule } from './app/app.module' 5 6 fetch('/assets/config.json') 7 8 .then((config) => { 9 if (environment.production) { 10 enableProdMode() 11 } 12 13 platformBrowserDynamic([{ provide: APP_CONFIG, useValue: config }]) 14 .bootstrapModule(AppModule) 15 .catch((err) => console.error(err)) 16 }) 17 platformBrowserDynamic([{ provide: APP_CONFIG, useValue: config }]) import { enableProdMode } from '@angular/core' 1 import { platformBrowserDynamic } from '@angular/platform-browser-dynamic' 2 import { environment } from './environments/environment' 3 import { AppConfig, APP_CONFIG } from './app.config' 4 import { AppModule } from './app/app.module' 5 6 fetch('/assets/config.json') 7 .then((response) => response.json()) 8 .then((config) => { 9 if (environment.production) { 10 enableProdMode() 11 } 12 13 14 .bootstrapModule(AppModule) 15 .catch((err) => console.error(err)) 16 }) 17
  61. Main.ts export class AppConfig { /* */ } export let

    APP_CONFIG = new InjectionToken<AppConfig>('APP_CONFIG') 1 2 3 4 5
  62. Main.ts export class AppConfig { /* */ } export let

    APP_CONFIG = new InjectionToken<AppConfig>('APP_CONFIG') 1 2 3 4 5 import { APP_CONFIG, AppConfig } from '...'; @Injectable({ providedIn: 'root' }) export class MyService constructor(@Inject(APP_CONFIG) private config: AppConfig) {} } 1 2 3 4 5 6 7
  63. Stateful import { /* ... */ } from '...'; @Component({

    selector: 'workspace-groups-meetups-list', templateUrl: './groups-meetups-list.component.html', styleUrls: ['./groups-meetups-list.component.scss'], }) export class GroupsMeetupsListComponent implements OnInit { items$: Observable<Meetup[]>; loading$: Observable<boolean>; constructor(private store: Store<any>) {} ngOnInit() { this.loading$ = this.store.pipe(select(fromGroupStore.selectIsLoading)); this.items$ = this.store.pipe(select(fromGroupStore.selectAllMeetups)); this.store.dispatch(fromGroupStore.getAllMeetupsFromGroup()); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
  64. Stateful import { /* ... */ } from '...'; @Component({

    selector: 'workspace-groups-meetups-list', templateUrl: './groups-meetups-list.component.html', styleUrls: ['./groups-meetups-list.component.scss'], }) export class GroupsMeetupsListComponent implements OnInit { items$: Observable<Meetup[]>; loading$: Observable<boolean>; constructor(private store: Store<any>) {} ngOnInit() { this.loading$ = this.store.pipe(select(fromGroupStore.selectIsLoading)); this.items$ = this.store.pipe(select(fromGroupStore.selectAllMeetups)); this.store.dispatch(fromGroupStore.getAllMeetupsFromGroup()); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 items$: Observable<Meetup[]>; loading$: Observable<boolean>; import { /* ... */ } from '...'; 1 2 @Component({ 3 selector: 'workspace-groups-meetups-list', 4 templateUrl: './groups-meetups-list.component.html', 5 styleUrls: ['./groups-meetups-list.component.scss'], 6 }) 7 export class GroupsMeetupsListComponent implements OnInit { 8 9 10 11 constructor(private store: Store<any>) {} 12 13 ngOnInit() { 14 this.loading$ = this.store.pipe(select(fromGroupStore.selectIsLoading)); 15 16 this.items$ = this.store.pipe(select(fromGroupStore.selectAllMeetups)); 17 18 this.store.dispatch(fromGroupStore.getAllMeetupsFromGroup()); 19 } 20 } 21
  65. Stateful import { /* ... */ } from '...'; @Component({

    selector: 'workspace-groups-meetups-list', templateUrl: './groups-meetups-list.component.html', styleUrls: ['./groups-meetups-list.component.scss'], }) export class GroupsMeetupsListComponent implements OnInit { items$: Observable<Meetup[]>; loading$: Observable<boolean>; constructor(private store: Store<any>) {} ngOnInit() { this.loading$ = this.store.pipe(select(fromGroupStore.selectIsLoading)); this.items$ = this.store.pipe(select(fromGroupStore.selectAllMeetups)); this.store.dispatch(fromGroupStore.getAllMeetupsFromGroup()); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 items$: Observable<Meetup[]>; loading$: Observable<boolean>; import { /* ... */ } from '...'; 1 2 @Component({ 3 selector: 'workspace-groups-meetups-list', 4 templateUrl: './groups-meetups-list.component.html', 5 styleUrls: ['./groups-meetups-list.component.scss'], 6 }) 7 export class GroupsMeetupsListComponent implements OnInit { 8 9 10 11 constructor(private store: Store<any>) {} 12 13 ngOnInit() { 14 this.loading$ = this.store.pipe(select(fromGroupStore.selectIsLoading)); 15 16 this.items$ = this.store.pipe(select(fromGroupStore.selectAllMeetups)); 17 18 this.store.dispatch(fromGroupStore.getAllMeetupsFromGroup()); 19 } 20 } 21 constructor(private store: Store<any>) {} import { /* ... */ } from '...'; 1 2 @Component({ 3 selector: 'workspace-groups-meetups-list', 4 templateUrl: './groups-meetups-list.component.html', 5 styleUrls: ['./groups-meetups-list.component.scss'], 6 }) 7 export class GroupsMeetupsListComponent implements OnInit { 8 items$: Observable<Meetup[]>; 9 loading$: Observable<boolean>; 10 11 12 13 ngOnInit() { 14 this.loading$ = this.store.pipe(select(fromGroupStore.selectIsLoading)); 15 16 this.items$ = this.store.pipe(select(fromGroupStore.selectAllMeetups)); 17 18 this.store.dispatch(fromGroupStore.getAllMeetupsFromGroup()); 19 } 20 } 21
  66. Stateful import { /* ... */ } from '...'; @Component({

    selector: 'workspace-groups-meetups-list', templateUrl: './groups-meetups-list.component.html', styleUrls: ['./groups-meetups-list.component.scss'], }) export class GroupsMeetupsListComponent implements OnInit { items$: Observable<Meetup[]>; loading$: Observable<boolean>; constructor(private store: Store<any>) {} ngOnInit() { this.loading$ = this.store.pipe(select(fromGroupStore.selectIsLoading)); this.items$ = this.store.pipe(select(fromGroupStore.selectAllMeetups)); this.store.dispatch(fromGroupStore.getAllMeetupsFromGroup()); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 items$: Observable<Meetup[]>; loading$: Observable<boolean>; import { /* ... */ } from '...'; 1 2 @Component({ 3 selector: 'workspace-groups-meetups-list', 4 templateUrl: './groups-meetups-list.component.html', 5 styleUrls: ['./groups-meetups-list.component.scss'], 6 }) 7 export class GroupsMeetupsListComponent implements OnInit { 8 9 10 11 constructor(private store: Store<any>) {} 12 13 ngOnInit() { 14 this.loading$ = this.store.pipe(select(fromGroupStore.selectIsLoading)); 15 16 this.items$ = this.store.pipe(select(fromGroupStore.selectAllMeetups)); 17 18 this.store.dispatch(fromGroupStore.getAllMeetupsFromGroup()); 19 } 20 } 21 constructor(private store: Store<any>) {} import { /* ... */ } from '...'; 1 2 @Component({ 3 selector: 'workspace-groups-meetups-list', 4 templateUrl: './groups-meetups-list.component.html', 5 styleUrls: ['./groups-meetups-list.component.scss'], 6 }) 7 export class GroupsMeetupsListComponent implements OnInit { 8 items$: Observable<Meetup[]>; 9 loading$: Observable<boolean>; 10 11 12 13 ngOnInit() { 14 this.loading$ = this.store.pipe(select(fromGroupStore.selectIsLoading)); 15 16 this.items$ = this.store.pipe(select(fromGroupStore.selectAllMeetups)); 17 18 this.store.dispatch(fromGroupStore.getAllMeetupsFromGroup()); 19 } 20 } 21 this.loading$ = this.store.pipe(select(fromGroupStore.selectIsLoading)); this.items$ = this.store.pipe(select(fromGroupStore.selectAllMeetups)); import { /* ... */ } from '...'; 1 2 @Component({ 3 selector: 'workspace-groups-meetups-list', 4 templateUrl: './groups-meetups-list.component.html', 5 styleUrls: ['./groups-meetups-list.component.scss'], 6 }) 7 export class GroupsMeetupsListComponent implements OnInit { 8 items$: Observable<Meetup[]>; 9 loading$: Observable<boolean>; 10 11 constructor(private store: Store<any>) {} 12 13 ngOnInit() { 14 15 16 17 18 this.store.dispatch(fromGroupStore.getAllMeetupsFromGroup()); 19 } 20 } 21
  67. Stateful import { /* ... */ } from '...'; @Component({

    selector: 'workspace-groups-meetups-list', templateUrl: './groups-meetups-list.component.html', styleUrls: ['./groups-meetups-list.component.scss'], }) export class GroupsMeetupsListComponent implements OnInit { items$: Observable<Meetup[]>; loading$: Observable<boolean>; constructor(private store: Store<any>) {} ngOnInit() { this.loading$ = this.store.pipe(select(fromGroupStore.selectIsLoading)); this.items$ = this.store.pipe(select(fromGroupStore.selectAllMeetups)); this.store.dispatch(fromGroupStore.getAllMeetupsFromGroup()); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 items$: Observable<Meetup[]>; loading$: Observable<boolean>; import { /* ... */ } from '...'; 1 2 @Component({ 3 selector: 'workspace-groups-meetups-list', 4 templateUrl: './groups-meetups-list.component.html', 5 styleUrls: ['./groups-meetups-list.component.scss'], 6 }) 7 export class GroupsMeetupsListComponent implements OnInit { 8 9 10 11 constructor(private store: Store<any>) {} 12 13 ngOnInit() { 14 this.loading$ = this.store.pipe(select(fromGroupStore.selectIsLoading)); 15 16 this.items$ = this.store.pipe(select(fromGroupStore.selectAllMeetups)); 17 18 this.store.dispatch(fromGroupStore.getAllMeetupsFromGroup()); 19 } 20 } 21 constructor(private store: Store<any>) {} import { /* ... */ } from '...'; 1 2 @Component({ 3 selector: 'workspace-groups-meetups-list', 4 templateUrl: './groups-meetups-list.component.html', 5 styleUrls: ['./groups-meetups-list.component.scss'], 6 }) 7 export class GroupsMeetupsListComponent implements OnInit { 8 items$: Observable<Meetup[]>; 9 loading$: Observable<boolean>; 10 11 12 13 ngOnInit() { 14 this.loading$ = this.store.pipe(select(fromGroupStore.selectIsLoading)); 15 16 this.items$ = this.store.pipe(select(fromGroupStore.selectAllMeetups)); 17 18 this.store.dispatch(fromGroupStore.getAllMeetupsFromGroup()); 19 } 20 } 21 this.loading$ = this.store.pipe(select(fromGroupStore.selectIsLoading)); this.items$ = this.store.pipe(select(fromGroupStore.selectAllMeetups)); import { /* ... */ } from '...'; 1 2 @Component({ 3 selector: 'workspace-groups-meetups-list', 4 templateUrl: './groups-meetups-list.component.html', 5 styleUrls: ['./groups-meetups-list.component.scss'], 6 }) 7 export class GroupsMeetupsListComponent implements OnInit { 8 items$: Observable<Meetup[]>; 9 loading$: Observable<boolean>; 10 11 constructor(private store: Store<any>) {} 12 13 ngOnInit() { 14 15 16 17 18 this.store.dispatch(fromGroupStore.getAllMeetupsFromGroup()); 19 } 20 } 21 this.store.dispatch(fromGroupStore.getAllMeetupsFromGroup()); import { /* ... */ } from '...'; 1 2 @Component({ 3 selector: 'workspace-groups-meetups-list', 4 templateUrl: './groups-meetups-list.component.html', 5 styleUrls: ['./groups-meetups-list.component.scss'], 6 }) 7 export class GroupsMeetupsListComponent implements OnInit { 8 items$: Observable<Meetup[]>; 9 loading$: Observable<boolean>; 10 11 constructor(private store: Store<any>) {} 12 13 ngOnInit() { 14 this.loading$ = this.store.pipe(select(fromGroupStore.selectIsLoading)); 15 16 this.items$ = this.store.pipe(select(fromGroupStore.selectAllMeetups)); 17 18 19 } 20 } 21
  68. Stateful import { /* ... */ } from '...'; @Component({

    selector: 'workspace-groups-meetups-list', templateUrl: './groups-meetups-list.component.html', styleUrls: ['./groups-meetups-list.component.scss'], }) export class GroupsMeetupsListComponent implements OnInit { items$: Observable<Meetup[]>; loading$: Observable<boolean>; constructor(private store: Store<any>) {} ngOnInit() { this.loading$ = this.store.pipe(select(fromGroupStore.selectIsLoading)); this.items$ = this.store.pipe(select(fromGroupStore.selectAllMeetups)); this.store.dispatch(fromGroupStore.getAllMeetupsFromGroup()); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 items$: Observable<Meetup[]>; loading$: Observable<boolean>; import { /* ... */ } from '...'; 1 2 @Component({ 3 selector: 'workspace-groups-meetups-list', 4 templateUrl: './groups-meetups-list.component.html', 5 styleUrls: ['./groups-meetups-list.component.scss'], 6 }) 7 export class GroupsMeetupsListComponent implements OnInit { 8 9 10 11 constructor(private store: Store<any>) {} 12 13 ngOnInit() { 14 this.loading$ = this.store.pipe(select(fromGroupStore.selectIsLoading)); 15 16 this.items$ = this.store.pipe(select(fromGroupStore.selectAllMeetups)); 17 18 this.store.dispatch(fromGroupStore.getAllMeetupsFromGroup()); 19 } 20 } 21 constructor(private store: Store<any>) {} import { /* ... */ } from '...'; 1 2 @Component({ 3 selector: 'workspace-groups-meetups-list', 4 templateUrl: './groups-meetups-list.component.html', 5 styleUrls: ['./groups-meetups-list.component.scss'], 6 }) 7 export class GroupsMeetupsListComponent implements OnInit { 8 items$: Observable<Meetup[]>; 9 loading$: Observable<boolean>; 10 11 12 13 ngOnInit() { 14 this.loading$ = this.store.pipe(select(fromGroupStore.selectIsLoading)); 15 16 this.items$ = this.store.pipe(select(fromGroupStore.selectAllMeetups)); 17 18 this.store.dispatch(fromGroupStore.getAllMeetupsFromGroup()); 19 } 20 } 21 this.loading$ = this.store.pipe(select(fromGroupStore.selectIsLoading)); this.items$ = this.store.pipe(select(fromGroupStore.selectAllMeetups)); import { /* ... */ } from '...'; 1 2 @Component({ 3 selector: 'workspace-groups-meetups-list', 4 templateUrl: './groups-meetups-list.component.html', 5 styleUrls: ['./groups-meetups-list.component.scss'], 6 }) 7 export class GroupsMeetupsListComponent implements OnInit { 8 items$: Observable<Meetup[]>; 9 loading$: Observable<boolean>; 10 11 constructor(private store: Store<any>) {} 12 13 ngOnInit() { 14 15 16 17 18 this.store.dispatch(fromGroupStore.getAllMeetupsFromGroup()); 19 } 20 } 21 this.store.dispatch(fromGroupStore.getAllMeetupsFromGroup()); import { /* ... */ } from '...'; 1 2 @Component({ 3 selector: 'workspace-groups-meetups-list', 4 templateUrl: './groups-meetups-list.component.html', 5 styleUrls: ['./groups-meetups-list.component.scss'], 6 }) 7 export class GroupsMeetupsListComponent implements OnInit { 8 items$: Observable<Meetup[]>; 9 loading$: Observable<boolean>; 10 11 constructor(private store: Store<any>) {} 12 13 ngOnInit() { 14 this.loading$ = this.store.pipe(select(fromGroupStore.selectIsLoading)); 15 16 this.items$ = this.store.pipe(select(fromGroupStore.selectAllMeetups)); 17 18 19 } 20 } 21 import { /* ... */ } from '...'; @Component({ selector: 'workspace-groups-meetups-list', templateUrl: './groups-meetups-list.component.html', styleUrls: ['./groups-meetups-list.component.scss'], }) export class GroupsMeetupsListComponent implements OnInit { items$: Observable<Meetup[]>; loading$: Observable<boolean>; constructor(private store: Store<any>) {} ngOnInit() { this.loading$ = this.store.pipe(select(fromGroupStore.selectIsLoading)); this.items$ = this.store.pipe(select(fromGroupStore.selectAllMeetups)); this.store.dispatch(fromGroupStore.getAllMeetupsFromGroup()); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
  69. Stateful <div class="container"> <h1 class="mt-3">All Gatherings of the Group</h1> <mat-progress-bar

    *ngIf="loading$ | async; else list" mode="indeterminate" ></mat-progress-bar> <ng-template #list> <workspace-meetup-list [items]="items$ | async"> </workspace-meetup-list> </ng-template> </div> 1 2 3 4 5 6 7 8 9 10 11 12 13
  70. Stateful <div class="container"> <h1 class="mt-3">All Gatherings of the Group</h1> <mat-progress-bar

    *ngIf="loading$ | async; else list" mode="indeterminate" ></mat-progress-bar> <ng-template #list> <workspace-meetup-list [items]="items$ | async"> </workspace-meetup-list> </ng-template> </div> 1 2 3 4 5 6 7 8 9 10 11 12 13 <workspace-meetup-list [items]="items$ | async"> </workspace-meetup-list> <div class="container"> 1 <h1 class="mt-3">All Gatherings of the Group</h1> 2 3 <mat-progress-bar 4 *ngIf="loading$ | async; else list" 5 mode="indeterminate" 6 ></mat-progress-bar> 7 8 <ng-template #list> 9 10 11 </ng-template> 12 </div> 13
  71. Stateless import { /* ... */ } from '...'; @Component({

    selector: 'workspace-meetup-list', templateUrl: './meetup-list.component.html', styleUrls: ['./meetup-list.component.scss'], }) export class MeetupListComponent { @Input() items: Meetup[] = []; } 1 2 3 4 5 6 7 8 9 10 11 12
  72. Stateless <div class="mb-20"> <ng-template #noItems> No items found... </ng-template> <div

    *ngIf="items?.length > 0; else noItems"> <ul> <li *ngFor="let item of items"> {{ item.name }} </li> </ul> </div> </div> 1 2 3 4 5 6 7 8 9 10 11 12 13 14
  73. Stateless <div class="mb-20"> <ng-template #noItems> No items found... </ng-template> <div

    *ngIf="items?.length > 0; else noItems"> <workspace-meetup-item *ngFor="let item of items" [item]="item" > </workspace-meetup-item> </div> </div> 1 2 3 4 5 6 7 8 9 10 11 12 13
  74. Stateless <div class="mb-20"> <ng-template #noItems> No items found... </ng-template> <div

    *ngIf="items?.length > 0; else noItems"> <workspace-meetup-item *ngFor="let item of items" [item]="item" (itemClicked)="navigateToItem($event)" > </workspace-meetup-item> </div> </div> 1 2 3 4 5 6 7 8 9 10 11 12 13 14
  75. Stateless <div class="mb-20"> <ng-template #noItems> No items found... </ng-template> <div

    *ngIf="items?.length > 0; else noItems"> <workspace-meetup-item *ngFor="let item of items" [item]="item" (itemClicked)="bubbleNavigateEvent($event)" > </workspace-meetup-item> </div> </div> 1 2 3 4 5 6 7 8 9 10 11 12 13 14
  76. Stateless import { /* ... */ } from '...'; @Component({

    selector: 'workspace-meetup-list', templateUrl: './meetup-list.component.html', styleUrls: ['./meetup-list.component.scss'], }) export class MeetupListComponent { @Input() items: Meetup[] = []; @Output() itemClicked = new EventEmitter(); bubbleNavigationEvent(meetup: Meetup) { this.itemClicked.emit(meetup); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
  77. Service @Injectable({ providedIn: 'root' }) export class MyService { //

    DON'T somethingHappened = new EventEmitter(); throwSomethingHappened(data: any) { this.somethingHappened.emit(data); } } 1 2 3 4 5 6 7 8 9 10 somethingHappened.subscribe(data => ...) 1
  78. Service @Injectable({ providedIn: 'root' }) export class MyService { //

    DON'T somethingHappened = new Subject(); throwSomethingHappened(data: any) { this.somethingHappened.next(data); } } 1 2 3 4 5 6 7 8 9 10 somethingHappened.subscribe(data => ...) 1
  79. Service @Injectable({ providedIn: 'root' }) export class MyService { private

    somethingHappenedInternal = new Subject(); get somethingHappened() { return this.somethingHappenedInternal.asObservable(); } throwSomethingHappened(data: any) { this.somethingHappened.next(data); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 somethingHappened.subscribe(data => ...) 1
  80. Service @Injectable({ providedIn: 'root' }) export class MyService { private

    somethingHappenedInternal = new Subject(); get somethingHappened() { return this.somethingHappenedInternal.asObservable(); } throwSomethingHappened(data: any) { this.somethingHappened.next(data); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 private somethingHappenedInternal = new Subject(); @Injectable({ providedIn: 'root' }) 1 export class MyService { 2 3 4 5 get somethingHappened() { 6 return this.somethingHappenedInternal.asObservable(); 7 } 8 9 throwSomethingHappened(data: any) { 10 this.somethingHappened.next(data); 11 } 12 } 13 somethingHappened.subscribe(data => ...) 1
  81. Service @Injectable({ providedIn: 'root' }) export class MyService { private

    somethingHappenedInternal = new Subject(); get somethingHappened() { return this.somethingHappenedInternal.asObservable(); } throwSomethingHappened(data: any) { this.somethingHappened.next(data); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 private somethingHappenedInternal = new Subject(); @Injectable({ providedIn: 'root' }) 1 export class MyService { 2 3 4 5 get somethingHappened() { 6 return this.somethingHappenedInternal.asObservable(); 7 } 8 9 throwSomethingHappened(data: any) { 10 this.somethingHappened.next(data); 11 } 12 } 13 get somethingHappened() { return this.somethingHappenedInternal.asObservable(); } @Injectable({ providedIn: 'root' }) 1 export class MyService { 2 3 private somethingHappenedInternal = new Subject(); 4 5 6 7 8 9 throwSomethingHappened(data: any) { 10 this.somethingHappened.next(data); 11 } 12 } 13 somethingHappened.subscribe(data => ...) 1
  82. Service @Injectable({ providedIn: 'root' }) export class MyService { private

    somethingHappenedInternal = new Subject(); get somethingHappened() { return this.somethingHappenedInternal.asObservable(); } throwSomethingHappened(data: any) { this.somethingHappened.next(data); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 private somethingHappenedInternal = new Subject(); @Injectable({ providedIn: 'root' }) 1 export class MyService { 2 3 4 5 get somethingHappened() { 6 return this.somethingHappenedInternal.asObservable(); 7 } 8 9 throwSomethingHappened(data: any) { 10 this.somethingHappened.next(data); 11 } 12 } 13 get somethingHappened() { return this.somethingHappenedInternal.asObservable(); } @Injectable({ providedIn: 'root' }) 1 export class MyService { 2 3 private somethingHappenedInternal = new Subject(); 4 5 6 7 8 9 throwSomethingHappened(data: any) { 10 this.somethingHappened.next(data); 11 } 12 } 13 @Injectable({ providedIn: 'root' }) export class MyService { private somethingHappenedInternal = new Subject(); get somethingHappened() { return this.somethingHappenedInternal.asObservable(); } throwSomethingHappened(data: any) { this.somethingHappened.next(data); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 somethingHappened.subscribe(data => ...) 1
  83. "if you're starting with angular, you do not need an

    angular course, you need an rxjs course"
  84. "if you're starting with angular, you do not need an

    angular course, you need an rxjs course" Colleague - some time ago
  85. @Component({ selector: "my-app", template: `{{ todos | json }}` })

    export class AppComponent implements OnInit { todos: any[]; constructor(private http: HttpClient) {} ngOnInit(): void { this.http .get<any[]>("https://...") .subscribe(result => { this.todos = result; }); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
  86. @Component({ selector: "my-app", template: `{{ todos | json }}` })

    export class AppComponent implements OnInit { todos: any[]; constructor(private http: HttpClient) {} ngOnInit(): void { this.http .get<any[]>("https://...") .subscribe(result => { this.todos = result; }); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 template: `{{ todos | json }}` todos: any[]; @Component({ 1 selector: "my-app", 2 3 }) 4 export class AppComponent implements OnInit { 5 6 7 constructor(private http: HttpClient) {} 8 9 ngOnInit(): void { 10 this.http 11 .get<any[]>("https://...") 12 .subscribe(result => { 13 this.todos = result; 14 }); 15 } 16 } 17
  87. @Component({ selector: "my-app", template: `{{ todos | json }}` })

    export class AppComponent implements OnInit { todos: any[]; constructor(private http: HttpClient) {} ngOnInit(): void { this.http .get<any[]>("https://...") .subscribe(result => { this.todos = result; }); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 template: `{{ todos | json }}` todos: any[]; @Component({ 1 selector: "my-app", 2 3 }) 4 export class AppComponent implements OnInit { 5 6 7 constructor(private http: HttpClient) {} 8 9 ngOnInit(): void { 10 this.http 11 .get<any[]>("https://...") 12 .subscribe(result => { 13 this.todos = result; 14 }); 15 } 16 } 17 ngOnInit(): void { this.http .get<any[]>("https://...") .subscribe(result => { this.todos = result; }); } @Component({ 1 selector: "my-app", 2 template: `{{ todos | json }}` 3 }) 4 export class AppComponent implements OnInit { 5 todos: any[]; 6 7 constructor(private http: HttpClient) {} 8 9 10 11 12 13 14 15 16 } 17
  88. .subscribe(result => this.todos = result); @Component({ 1 selector: "my-app", 2

    template: `{{ todos | json }}` 3 }) 4 export class AppComponent implements OnInit { 5 todos: any[]; 6 7 constructor(private http: HttpClient) {} 8 9 ngOnInit(): void { 10 this.http 11 .get<any[]>("https://...") 12 13 } 14 } 15
  89. @Component({ selector: "my-app", template: `{{ todos$ | async | json

    }}`, styleUrls: ["./app.component.css"] }) export class AppComponent implements OnInit { todos$: Observable<any[]>; constructor(private http: HttpClient) {} ngOnInit(): void { this.todos$ = this.http.get<any[]>("https://...") } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
  90. @Component({ selector: "my-app", template: `{{ todos$ | async | json

    }}`, styleUrls: ["./app.component.css"] }) export class AppComponent implements OnInit { todos$: Observable<any[]>; constructor(private http: HttpClient) {} ngOnInit(): void { this.todos$ = this.http.get<any[]>("https://...") } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 template: `{{ todos$ | async | json }}`, ngOnInit(): void { this.todos$ = this.http.get<any[]>("https://...") @Component({ 1 selector: "my-app", 2 3 styleUrls: ["./app.component.css"] 4 }) 5 export class AppComponent implements OnInit { 6 todos$: Observable<any[]>; 7 8 constructor(private http: HttpClient) {} 9 10 11 12 13 } 14 } 15
  91. ngOnInit(): void { this.todos$ = this.http.get<any[]>("https://...") .pipe(tap(result => console.log(result))); @Component({

    1 selector: "my-app", 2 template: `{{ todos$ | async | json }}`, 3 styleUrls: ["./app.component.css"] 4 }) 5 export class AppComponent implements OnInit { 6 todos$: Observable<any[]>; 7 8 constructor(private http: HttpClient) {} 9 10 11 12 13 } 14 } 15
  92. @Component({ selector: "my-app", template: `{{ todos$ | async | json

    }}`, styleUrls: ["./app.component.css"] }) export class AppComponent implements OnInit { todos$: Observable<number>; constructor(private http: HttpClient) {} ngOnInit(): void { this.todos$ = this.http.get<any[]>("https://...") .pipe(map(result => result.length)); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
  93. @Component({ selector: "my-app", template: `{{ todos$ | async | json

    }}`, styleUrls: ["./app.component.css"] }) export class AppComponent implements OnInit { todos$: Observable<number>; constructor(private http: HttpClient) {} ngOnInit(): void { this.todos$ = this.http.get<any[]>("https://...") .pipe(map(result => result.length)); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 template: `{{ todos$ | async | json }}`, todos$: Observable<number>; @Component({ 1 selector: "my-app", 2 3 styleUrls: ["./app.component.css"] 4 }) 5 export class AppComponent implements OnInit { 6 7 8 constructor(private http: HttpClient) {} 9 10 ngOnInit(): void { 11 this.todos$ = this.http.get<any[]>("https://...") 12 .pipe(map(result => result.length)); 13 } 14 } 15
  94. @Component({ selector: "my-app", template: `{{ todos$ | async | json

    }}`, styleUrls: ["./app.component.css"] }) export class AppComponent implements OnInit { todos$: Observable<number>; constructor(private http: HttpClient) {} ngOnInit(): void { this.todos$ = this.http.get<any[]>("https://...") .pipe(map(result => result.length)); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 template: `{{ todos$ | async | json }}`, todos$: Observable<number>; @Component({ 1 selector: "my-app", 2 3 styleUrls: ["./app.component.css"] 4 }) 5 export class AppComponent implements OnInit { 6 7 8 constructor(private http: HttpClient) {} 9 10 ngOnInit(): void { 11 this.todos$ = this.http.get<any[]>("https://...") 12 .pipe(map(result => result.length)); 13 } 14 } 15 ngOnInit(): void { this.todos$ = this.http.get<any[]>("https://...") .pipe(map(result => result.length)); @Component({ 1 selector: "my-app", 2 template: `{{ todos$ | async | json }}`, 3 styleUrls: ["./app.component.css"] 4 }) 5 export class AppComponent implements OnInit { 6 todos$: Observable<number>; 7 8 constructor(private http: HttpClient) {} 9 10 11 12 13 } 14 } 15
  95. @Component({ selector: "my-app", template: `{{ todos$ | async | json

    }}`, styleUrls: ["./app.component.css"] }) export class AppComponent implements OnInit { todos$: Observable<any[]>; constructor(private http: HttpClient) {} ngOnInit(): void { this.todos$ = this.http.get<any[]>("https://...") .pipe(map(result => result.filter(x => x.id > 5))); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
  96. @Component({ selector: "my-app", template: ` {{ todo | json }}

    `, styleUrls: ["./app.component.css"] }) export class AppComponent implements OnInit { todo: any; url = "https://jsonplaceholder.typicode.com/todos"; constructor(private http: HttpClient) {} ngOnInit(): void { this.http .get<any[]>(this.url) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
  97. @Component({ selector: "my-app", template: ` {{ todo | json }}

    `, styleUrls: ["./app.component.css"] }) export class AppComponent implements OnInit { todo: any; url = "https://jsonplaceholder.typicode.com/todos"; constructor(private http: HttpClient) {} ngOnInit(): void { this.http .get<any[]>(this.url) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 {{ todo | json }} todo: any; @Component({ 1 selector: "my-app", 2 template: ` 3 4 `, 5 styleUrls: ["./app.component.css"] 6 }) 7 export class AppComponent implements OnInit { 8 9 url = "https://jsonplaceholder.typicode.com/todos"; 10 11 constructor(private http: HttpClient) {} 12 13 ngOnInit(): void { 14 this.http 15 .get<any[]>(this.url) 16 17 18 19 20 21 } 22 } 23
  98. @Component({ selector: "my-app", template: ` {{ todo | json }}

    `, styleUrls: ["./app.component.css"] }) export class AppComponent implements OnInit { todo: any; url = "https://jsonplaceholder.typicode.com/todos"; constructor(private http: HttpClient) {} ngOnInit(): void { this.http .get<any[]>(this.url) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 {{ todo | json }} todo: any; @Component({ 1 selector: "my-app", 2 template: ` 3 4 `, 5 styleUrls: ["./app.component.css"] 6 }) 7 export class AppComponent implements OnInit { 8 9 url = "https://jsonplaceholder.typicode.com/todos"; 10 11 constructor(private http: HttpClient) {} 12 13 ngOnInit(): void { 14 this.http 15 .get<any[]>(this.url) 16 17 18 19 20 21 } 22 } 23 url = "https://jsonplaceholder.typicode.com/todos"; this.http .get<any[]>(this.url) @Component({ 1 selector: "my-app", 2 template: ` 3 {{ todo | json }} 4 `, 5 styleUrls: ["./app.component.css"] 6 }) 7 export class AppComponent implements OnInit { 8 todo: any; 9 10 11 constructor(private http: HttpClient) {} 12 13 ngOnInit(): void { 14 15 16 17 18 19 20 21 } 22 } 23
  99. @Component({ selector: "my-app", template: ` {{ todo | json }}

    `, styleUrls: ["./app.component.css"] }) export class AppComponent implements OnInit { todo: any; url = "https://jsonplaceholder.typicode.com/todos"; constructor(private http: HttpClient) {} ngOnInit(): void { this.http .get<any[]>(this.url) .subscribe(allItems => { }); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
  100. @Component({ selector: "my-app", template: ` {{ todo | json }}

    `, styleUrls: ["./app.component.css"] }) export class AppComponent implements OnInit { todo: any; url = "https://jsonplaceholder.typicode.com/todos"; constructor(private http: HttpClient) {} ngOnInit(): void { this.http .get<any[]>(this.url) .subscribe(allItems => { this.http .get(this.url + "/" + allItems[0].id) }); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
  101. @Component({ selector: "my-app", template: ` {{ todo | json }}

    `, styleUrls: ["./app.component.css"] }) export class AppComponent implements OnInit { todo: any; url = "https://jsonplaceholder.typicode.com/todos"; constructor(private http: HttpClient) {} ngOnInit(): void { this.http .get<any[]>(this.url) .subscribe(allItems => { this.http .get(this.url + "/" + allItems[0].id) .subscribe(singleItem => (this.todo = singleItem)); }); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
  102. .subscribe(allItems => { .subscribe(singleItem => (this.todo = singleItem)); @Component({ 1

    selector: "my-app", 2 template: ` 3 {{ todo | json }} 4 `, 5 styleUrls: ["./app.component.css"] 6 }) 7 export class AppComponent implements OnInit { 8 todo: any; 9 url = "https://jsonplaceholder.typicode.com/todos"; 10 11 constructor(private http: HttpClient) {} 12 13 ngOnInit(): void { 14 this.http 15 .get<any[]>(this.url) 16 17 this.http 18 .get(this.url + "/" + allItems[0].id) 19 20 }); 21 } 22 } 23
  103. switchMap(allItems => { return this.http.get(this.url + "/" + allItems[0].id); })

    @Component({ 1 selector: "my-app", 2 template: ` 3 {{ todo$ | async | json }} 4 `, 5 styleUrls: ["./app.component.css"] 6 }) 7 export class AppComponent implements OnInit { 8 todo$: Observable<any>; 9 url = "https://jsonplaceholder.typicode.com/todos"; 10 11 constructor(private http: HttpClient) {} 12 13 ngOnInit(): void { 14 this.todo$ = this.http.get<any[]>(this.url).pipe( 15 16 17 18 ); 19 } 20 } 21
  104. switchMap(allItems => this.http.get(this.url + "/" + allItems[0].id)) @Component({ 1 selector:

    "my-app", 2 template: ` 3 {{ todo$ | async | json }} 4 `, 5 styleUrls: ["./app.component.css"] 6 }) 7 export class AppComponent implements OnInit { 8 todo$: Observable<any>; 9 url = "https://jsonplaceholder.typicode.com/todos"; 10 11 constructor(private http: HttpClient) {} 12 13 ngOnInit(): void { 14 this.todo$ = this.http.get<any[]>(this.url).pipe( 15 16 ); 17 } 18 } 19
  105. @Component({ selector: "my-app", template: ` {{ amount }} <button (click)="sendMoney()">Send

    $$$</button> `, styleUrls: ["./app.component.css"] }) export class AppComponent { amount: number; url = "https://bank.com/transferMoney"; constructor(private http: HttpClient) {} sendMoney(): void { this.http .post(this.url, { transfer: 100 }) .pipe(switchMap(() => this.http.get("..."))) .subscribe((newAmount) => { this.amount = newAmount; alert("transferred successfully") }); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
  106. @Component({ selector: "my-app", template: ` {{ amount }} <button (click)="sendMoney()">Send

    $$$</button> `, styleUrls: ["./app.component.css"] }) export class AppComponent { amount: number; url = "https://bank.com/transferMoney"; constructor(private http: HttpClient) {} sendMoney(): void { this.http .post(this.url, { transfer: 100 }) .pipe(switchMap(() => this.http.get("..."))) .subscribe((newAmount) => { this.amount = newAmount; alert("transferred successfully") }); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 {{ amount }} amount: number; @Component({ 1 selector: "my-app", 2 template: ` 3 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 10 url = "https://bank.com/transferMoney"; 11 12 constructor(private http: HttpClient) {} 13 14 sendMoney(): void { 15 this.http 16 .post(this.url, { transfer: 100 }) 17 .pipe(switchMap(() => this.http.get("..."))) 18 .subscribe((newAmount) => { 19 this.amount = newAmount; 20 alert("transferred successfully") 21 }); 22 } 23 } 24
  107. @Component({ selector: "my-app", template: ` {{ amount }} <button (click)="sendMoney()">Send

    $$$</button> `, styleUrls: ["./app.component.css"] }) export class AppComponent { amount: number; url = "https://bank.com/transferMoney"; constructor(private http: HttpClient) {} sendMoney(): void { this.http .post(this.url, { transfer: 100 }) .pipe(switchMap(() => this.http.get("..."))) .subscribe((newAmount) => { this.amount = newAmount; alert("transferred successfully") }); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 {{ amount }} amount: number; @Component({ 1 selector: "my-app", 2 template: ` 3 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 10 url = "https://bank.com/transferMoney"; 11 12 constructor(private http: HttpClient) {} 13 14 sendMoney(): void { 15 this.http 16 .post(this.url, { transfer: 100 }) 17 .pipe(switchMap(() => this.http.get("..."))) 18 .subscribe((newAmount) => { 19 this.amount = newAmount; 20 alert("transferred successfully") 21 }); 22 } 23 } 24 url = "https://bank.com/transferMoney"; @Component({ 1 selector: "my-app", 2 template: ` 3 {{ amount }} 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 amount: number; 10 11 12 constructor(private http: HttpClient) {} 13 14 sendMoney(): void { 15 this.http 16 .post(this.url, { transfer: 100 }) 17 .pipe(switchMap(() => this.http.get("..."))) 18 .subscribe((newAmount) => { 19 this.amount = newAmount; 20 alert("transferred successfully") 21 }); 22 } 23 } 24
  108. @Component({ selector: "my-app", template: ` {{ amount }} <button (click)="sendMoney()">Send

    $$$</button> `, styleUrls: ["./app.component.css"] }) export class AppComponent { amount: number; url = "https://bank.com/transferMoney"; constructor(private http: HttpClient) {} sendMoney(): void { this.http .post(this.url, { transfer: 100 }) .pipe(switchMap(() => this.http.get("..."))) .subscribe((newAmount) => { this.amount = newAmount; alert("transferred successfully") }); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 {{ amount }} amount: number; @Component({ 1 selector: "my-app", 2 template: ` 3 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 10 url = "https://bank.com/transferMoney"; 11 12 constructor(private http: HttpClient) {} 13 14 sendMoney(): void { 15 this.http 16 .post(this.url, { transfer: 100 }) 17 .pipe(switchMap(() => this.http.get("..."))) 18 .subscribe((newAmount) => { 19 this.amount = newAmount; 20 alert("transferred successfully") 21 }); 22 } 23 } 24 url = "https://bank.com/transferMoney"; @Component({ 1 selector: "my-app", 2 template: ` 3 {{ amount }} 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 amount: number; 10 11 12 constructor(private http: HttpClient) {} 13 14 sendMoney(): void { 15 this.http 16 .post(this.url, { transfer: 100 }) 17 .pipe(switchMap(() => this.http.get("..."))) 18 .subscribe((newAmount) => { 19 this.amount = newAmount; 20 alert("transferred successfully") 21 }); 22 } 23 } 24 sendMoney(): void { this.http .post(this.url, { transfer: 100 }) .pipe(switchMap(() => this.http.get("..."))) .subscribe((newAmount) => { this.amount = newAmount; alert("transferred successfully") }); } @Component({ 1 selector: "my-app", 2 template: ` 3 {{ amount }} 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 amount: number; 10 url = "https://bank.com/transferMoney"; 11 12 constructor(private http: HttpClient) {} 13 14 15 16 17 18 19 20 21 22 23 } 24
  109. @Component({ selector: "my-app", template: ` {{ amount }} <button (click)="sendMoney()">Send

    $$$</button> `, styleUrls: ["./app.component.css"] }) export class AppComponent { amount: number; url = "https://bank.com/transferMoney"; constructor(private http: HttpClient) {} sendMoney(): void { this.http .post(this.url, { transfer: 100 }) .pipe(switchMap(() => this.http.get("..."))) .subscribe((newAmount) => { this.amount = newAmount; alert("transferred successfully") }); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 {{ amount }} amount: number; @Component({ 1 selector: "my-app", 2 template: ` 3 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 10 url = "https://bank.com/transferMoney"; 11 12 constructor(private http: HttpClient) {} 13 14 sendMoney(): void { 15 this.http 16 .post(this.url, { transfer: 100 }) 17 .pipe(switchMap(() => this.http.get("..."))) 18 .subscribe((newAmount) => { 19 this.amount = newAmount; 20 alert("transferred successfully") 21 }); 22 } 23 } 24 url = "https://bank.com/transferMoney"; @Component({ 1 selector: "my-app", 2 template: ` 3 {{ amount }} 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 amount: number; 10 11 12 constructor(private http: HttpClient) {} 13 14 sendMoney(): void { 15 this.http 16 .post(this.url, { transfer: 100 }) 17 .pipe(switchMap(() => this.http.get("..."))) 18 .subscribe((newAmount) => { 19 this.amount = newAmount; 20 alert("transferred successfully") 21 }); 22 } 23 } 24 sendMoney(): void { this.http .post(this.url, { transfer: 100 }) .pipe(switchMap(() => this.http.get("..."))) .subscribe((newAmount) => { this.amount = newAmount; alert("transferred successfully") }); } @Component({ 1 selector: "my-app", 2 template: ` 3 {{ amount }} 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 amount: number; 10 url = "https://bank.com/transferMoney"; 11 12 constructor(private http: HttpClient) {} 13 14 15 16 17 18 19 20 21 22 23 } 24 this.http .post(this.url, { transfer: 100 }) @Component({ 1 selector: "my-app", 2 template: ` 3 {{ amount }} 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 amount: number; 10 url = "https://bank.com/transferMoney"; 11 12 constructor(private http: HttpClient) {} 13 14 sendMoney(): void { 15 16 17 .pipe(switchMap(() => this.http.get("..."))) 18 .subscribe((newAmount) => { 19 this.amount = newAmount; 20 alert("transferred successfully") 21 }); 22 } 23 } 24
  110. @Component({ selector: "my-app", template: ` {{ amount }} <button (click)="sendMoney()">Send

    $$$</button> `, styleUrls: ["./app.component.css"] }) export class AppComponent { amount: number; url = "https://bank.com/transferMoney"; constructor(private http: HttpClient) {} sendMoney(): void { this.http .post(this.url, { transfer: 100 }) .pipe(switchMap(() => this.http.get("..."))) .subscribe((newAmount) => { this.amount = newAmount; alert("transferred successfully") }); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 {{ amount }} amount: number; @Component({ 1 selector: "my-app", 2 template: ` 3 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 10 url = "https://bank.com/transferMoney"; 11 12 constructor(private http: HttpClient) {} 13 14 sendMoney(): void { 15 this.http 16 .post(this.url, { transfer: 100 }) 17 .pipe(switchMap(() => this.http.get("..."))) 18 .subscribe((newAmount) => { 19 this.amount = newAmount; 20 alert("transferred successfully") 21 }); 22 } 23 } 24 url = "https://bank.com/transferMoney"; @Component({ 1 selector: "my-app", 2 template: ` 3 {{ amount }} 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 amount: number; 10 11 12 constructor(private http: HttpClient) {} 13 14 sendMoney(): void { 15 this.http 16 .post(this.url, { transfer: 100 }) 17 .pipe(switchMap(() => this.http.get("..."))) 18 .subscribe((newAmount) => { 19 this.amount = newAmount; 20 alert("transferred successfully") 21 }); 22 } 23 } 24 sendMoney(): void { this.http .post(this.url, { transfer: 100 }) .pipe(switchMap(() => this.http.get("..."))) .subscribe((newAmount) => { this.amount = newAmount; alert("transferred successfully") }); } @Component({ 1 selector: "my-app", 2 template: ` 3 {{ amount }} 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 amount: number; 10 url = "https://bank.com/transferMoney"; 11 12 constructor(private http: HttpClient) {} 13 14 15 16 17 18 19 20 21 22 23 } 24 this.http .post(this.url, { transfer: 100 }) @Component({ 1 selector: "my-app", 2 template: ` 3 {{ amount }} 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 amount: number; 10 url = "https://bank.com/transferMoney"; 11 12 constructor(private http: HttpClient) {} 13 14 sendMoney(): void { 15 16 17 .pipe(switchMap(() => this.http.get("..."))) 18 .subscribe((newAmount) => { 19 this.amount = newAmount; 20 alert("transferred successfully") 21 }); 22 } 23 } 24 .pipe(switchMap(() => this.http.get("..."))) @Component({ 1 selector: "my-app", 2 template: ` 3 {{ amount }} 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 amount: number; 10 url = "https://bank.com/transferMoney"; 11 12 constructor(private http: HttpClient) {} 13 14 sendMoney(): void { 15 this.http 16 .post(this.url, { transfer: 100 }) 17 18 .subscribe((newAmount) => { 19 this.amount = newAmount; 20 alert("transferred successfully") 21 }); 22 } 23 } 24
  111. @Component({ selector: "my-app", template: ` {{ amount }} <button (click)="sendMoney()">Send

    $$$</button> `, styleUrls: ["./app.component.css"] }) export class AppComponent { amount: number; url = "https://bank.com/transferMoney"; constructor(private http: HttpClient) {} sendMoney(): void { this.http .post(this.url, { transfer: 100 }) .pipe(switchMap(() => this.http.get("..."))) .subscribe((newAmount) => { this.amount = newAmount; alert("transferred successfully") }); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 {{ amount }} amount: number; @Component({ 1 selector: "my-app", 2 template: ` 3 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 10 url = "https://bank.com/transferMoney"; 11 12 constructor(private http: HttpClient) {} 13 14 sendMoney(): void { 15 this.http 16 .post(this.url, { transfer: 100 }) 17 .pipe(switchMap(() => this.http.get("..."))) 18 .subscribe((newAmount) => { 19 this.amount = newAmount; 20 alert("transferred successfully") 21 }); 22 } 23 } 24 url = "https://bank.com/transferMoney"; @Component({ 1 selector: "my-app", 2 template: ` 3 {{ amount }} 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 amount: number; 10 11 12 constructor(private http: HttpClient) {} 13 14 sendMoney(): void { 15 this.http 16 .post(this.url, { transfer: 100 }) 17 .pipe(switchMap(() => this.http.get("..."))) 18 .subscribe((newAmount) => { 19 this.amount = newAmount; 20 alert("transferred successfully") 21 }); 22 } 23 } 24 sendMoney(): void { this.http .post(this.url, { transfer: 100 }) .pipe(switchMap(() => this.http.get("..."))) .subscribe((newAmount) => { this.amount = newAmount; alert("transferred successfully") }); } @Component({ 1 selector: "my-app", 2 template: ` 3 {{ amount }} 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 amount: number; 10 url = "https://bank.com/transferMoney"; 11 12 constructor(private http: HttpClient) {} 13 14 15 16 17 18 19 20 21 22 23 } 24 this.http .post(this.url, { transfer: 100 }) @Component({ 1 selector: "my-app", 2 template: ` 3 {{ amount }} 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 amount: number; 10 url = "https://bank.com/transferMoney"; 11 12 constructor(private http: HttpClient) {} 13 14 sendMoney(): void { 15 16 17 .pipe(switchMap(() => this.http.get("..."))) 18 .subscribe((newAmount) => { 19 this.amount = newAmount; 20 alert("transferred successfully") 21 }); 22 } 23 } 24 .pipe(switchMap(() => this.http.get("..."))) @Component({ 1 selector: "my-app", 2 template: ` 3 {{ amount }} 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 amount: number; 10 url = "https://bank.com/transferMoney"; 11 12 constructor(private http: HttpClient) {} 13 14 sendMoney(): void { 15 this.http 16 .post(this.url, { transfer: 100 }) 17 18 .subscribe((newAmount) => { 19 this.amount = newAmount; 20 alert("transferred successfully") 21 }); 22 } 23 } 24 .subscribe((newAmount) => { this.amount = newAmount; alert("transferred successfully") }); @Component({ 1 selector: "my-app", 2 template: ` 3 {{ amount }} 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 amount: number; 10 url = "https://bank.com/transferMoney"; 11 12 constructor(private http: HttpClient) {} 13 14 sendMoney(): void { 15 this.http 16 .post(this.url, { transfer: 100 }) 17 .pipe(switchMap(() => this.http.get("..."))) 18 19 20 21 22 } 23 } 24
  112. @Component({ selector: "my-app", template: ` {{ amount }} <button (click)="sendMoney()">Send

    $$$</button> `, styleUrls: ["./app.component.css"] }) export class AppComponent { amount: number; url = "https://bank.com/transferMoney"; constructor(private http: HttpClient) {} sendMoney(): void { this.http .post(this.url, { transfer: 100 }) .pipe(switchMap(() => this.http.get("..."))) .subscribe((newAmount) => { this.amount = newAmount; alert("transferred successfully") }); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 {{ amount }} amount: number; @Component({ 1 selector: "my-app", 2 template: ` 3 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 10 url = "https://bank.com/transferMoney"; 11 12 constructor(private http: HttpClient) {} 13 14 sendMoney(): void { 15 this.http 16 .post(this.url, { transfer: 100 }) 17 .pipe(switchMap(() => this.http.get("..."))) 18 .subscribe((newAmount) => { 19 this.amount = newAmount; 20 alert("transferred successfully") 21 }); 22 } 23 } 24 url = "https://bank.com/transferMoney"; @Component({ 1 selector: "my-app", 2 template: ` 3 {{ amount }} 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 amount: number; 10 11 12 constructor(private http: HttpClient) {} 13 14 sendMoney(): void { 15 this.http 16 .post(this.url, { transfer: 100 }) 17 .pipe(switchMap(() => this.http.get("..."))) 18 .subscribe((newAmount) => { 19 this.amount = newAmount; 20 alert("transferred successfully") 21 }); 22 } 23 } 24 sendMoney(): void { this.http .post(this.url, { transfer: 100 }) .pipe(switchMap(() => this.http.get("..."))) .subscribe((newAmount) => { this.amount = newAmount; alert("transferred successfully") }); } @Component({ 1 selector: "my-app", 2 template: ` 3 {{ amount }} 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 amount: number; 10 url = "https://bank.com/transferMoney"; 11 12 constructor(private http: HttpClient) {} 13 14 15 16 17 18 19 20 21 22 23 } 24 this.http .post(this.url, { transfer: 100 }) @Component({ 1 selector: "my-app", 2 template: ` 3 {{ amount }} 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 amount: number; 10 url = "https://bank.com/transferMoney"; 11 12 constructor(private http: HttpClient) {} 13 14 sendMoney(): void { 15 16 17 .pipe(switchMap(() => this.http.get("..."))) 18 .subscribe((newAmount) => { 19 this.amount = newAmount; 20 alert("transferred successfully") 21 }); 22 } 23 } 24 .pipe(switchMap(() => this.http.get("..."))) @Component({ 1 selector: "my-app", 2 template: ` 3 {{ amount }} 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 amount: number; 10 url = "https://bank.com/transferMoney"; 11 12 constructor(private http: HttpClient) {} 13 14 sendMoney(): void { 15 this.http 16 .post(this.url, { transfer: 100 }) 17 18 .subscribe((newAmount) => { 19 this.amount = newAmount; 20 alert("transferred successfully") 21 }); 22 } 23 } 24 .subscribe((newAmount) => { this.amount = newAmount; alert("transferred successfully") }); @Component({ 1 selector: "my-app", 2 template: ` 3 {{ amount }} 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 amount: number; 10 url = "https://bank.com/transferMoney"; 11 12 constructor(private http: HttpClient) {} 13 14 sendMoney(): void { 15 this.http 16 .post(this.url, { transfer: 100 }) 17 .pipe(switchMap(() => this.http.get("..."))) 18 19 20 21 22 } 23 } 24 sendMoney(): void { this.http .post(this.url, { transfer: 100 }) .pipe(switchMap(() => this.http.get("..."))) .subscribe((newAmount) => { this.amount = newAmount; alert("transferred successfully") }); } @Component({ 1 selector: "my-app", 2 template: ` 3 {{ amount }} 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 amount: number; 10 url = "https://bank.com/transferMoney"; 11 12 constructor(private http: HttpClient) {} 13 14 15 16 17 18 19 20 21 22 23 } 24
  113. @Component({ selector: "my-app", template: ` {{ amount }} <button (click)="sendMoney()">Send

    $$$</button> `, styleUrls: ["./app.component.css"] }) export class AppComponent { amount: number; url = "https://bank.com/transferMoney"; constructor(private http: HttpClient) {} sendMoney(): void { this.http .post(this.url, { transfer: 100 }) .pipe(mergeMap(() => this.http.get("..."))) .subscribe((newAmount) => { this.amount = newAmount; alert("transferred successfully") }); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
  114. @Component({ selector: "my-app", template: ` {{ amount }} <button (click)="sendMoney()">Send

    $$$</button> `, styleUrls: ["./app.component.css"] }) export class AppComponent { amount: number; url = "https://bank.com/transferMoney"; constructor(private http: HttpClient) {} sendMoney(): void { this.http .post(this.url, { transfer: 100 }) .pipe(mergeMap(() => this.http.get("..."))) .subscribe((newAmount) => { this.amount = newAmount; alert("transferred successfully") }); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 .pipe(mergeMap(() => this.http.get("..."))) @Component({ 1 selector: "my-app", 2 template: ` 3 {{ amount }} 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 amount: number; 10 url = "https://bank.com/transferMoney"; 11 12 constructor(private http: HttpClient) {} 13 14 sendMoney(): void { 15 this.http 16 .post(this.url, { transfer: 100 }) 17 18 .subscribe((newAmount) => { 19 this.amount = newAmount; 20 alert("transferred successfully") 21 }); 22 } 23 } 24
  115. @Component({ selector: "my-app", template: ` {{ amount }} <button (click)="sendMoney()">Send

    $$$</button> `, styleUrls: ["./app.component.css"] }) export class AppComponent { amount: number; url = "https://bank.com/transferMoney"; constructor(private http: HttpClient) {} sendMoney(): void { this.http .post(this.url, { transfer: 100 }) .pipe(mergeMap(() => this.http.get("..."))) .subscribe((newAmount) => { this.amount = newAmount; alert("transferred successfully") }); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 .pipe(mergeMap(() => this.http.get("..."))) @Component({ 1 selector: "my-app", 2 template: ` 3 {{ amount }} 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 amount: number; 10 url = "https://bank.com/transferMoney"; 11 12 constructor(private http: HttpClient) {} 13 14 sendMoney(): void { 15 this.http 16 .post(this.url, { transfer: 100 }) 17 18 .subscribe((newAmount) => { 19 this.amount = newAmount; 20 alert("transferred successfully") 21 }); 22 } 23 } 24 .subscribe((newAmount) => { this.amount = newAmount; alert("transferred successfully") }); } @Component({ 1 selector: "my-app", 2 template: ` 3 {{ amount }} 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 amount: number; 10 url = "https://bank.com/transferMoney"; 11 12 constructor(private http: HttpClient) {} 13 14 sendMoney(): void { 15 this.http 16 .post(this.url, { transfer: 100 }) 17 .pipe(mergeMap(() => this.http.get("..."))) 18 19 20 21 22 23 } 24
  116. @Component({ selector: "my-app", template: ` {{ amount }} <button (click)="sendMoney()">Send

    $$$</button> `, styleUrls: ["./app.component.css"] }) export class AppComponent { amount: number; url = "https://bank.com/transferMoney"; constructor(private http: HttpClient) {} sendMoney(): void { this.http .post(this.url, { transfer: 100 }) .pipe(concatMap(() => this.http.get("..."))) .subscribe((newAmount) => { this.amount = newAmount; alert("transferred successfully") }); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
  117. @Component({ selector: "my-app", template: ` {{ amount }} <button (click)="sendMoney()">Send

    $$$</button> `, styleUrls: ["./app.component.css"] }) export class AppComponent { amount: number; url = "https://bank.com/transferMoney"; constructor(private http: HttpClient) {} sendMoney(): void { this.http .post(this.url, { transfer: 100 }) .pipe(concatMap(() => this.http.get("..."))) .subscribe((newAmount) => { this.amount = newAmount; alert("transferred successfully") }); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 .pipe(concatMap(() => this.http.get("..."))) @Component({ 1 selector: "my-app", 2 template: ` 3 {{ amount }} 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 amount: number; 10 url = "https://bank.com/transferMoney"; 11 12 constructor(private http: HttpClient) {} 13 14 sendMoney(): void { 15 this.http 16 .post(this.url, { transfer: 100 }) 17 18 .subscribe((newAmount) => { 19 this.amount = newAmount; 20 alert("transferred successfully") 21 }); 22 } 23 } 24
  118. @Component({ selector: "my-app", template: ` {{ amount }} <button (click)="sendMoney()">Send

    $$$</button> `, styleUrls: ["./app.component.css"] }) export class AppComponent { amount: number; url = "https://bank.com/transferMoney"; constructor(private http: HttpClient) {} sendMoney(): void { this.http .post(this.url, { transfer: 100 }) .pipe(concatMap(() => this.http.get("..."))) .subscribe((newAmount) => { this.amount = newAmount; alert("transferred successfully") }); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 .pipe(concatMap(() => this.http.get("..."))) @Component({ 1 selector: "my-app", 2 template: ` 3 {{ amount }} 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 amount: number; 10 url = "https://bank.com/transferMoney"; 11 12 constructor(private http: HttpClient) {} 13 14 sendMoney(): void { 15 this.http 16 .post(this.url, { transfer: 100 }) 17 18 .subscribe((newAmount) => { 19 this.amount = newAmount; 20 alert("transferred successfully") 21 }); 22 } 23 } 24 .subscribe((newAmount) => { this.amount = newAmount; alert("transferred successfully") }); } @Component({ 1 selector: "my-app", 2 template: ` 3 {{ amount }} 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 amount: number; 10 url = "https://bank.com/transferMoney"; 11 12 constructor(private http: HttpClient) {} 13 14 sendMoney(): void { 15 this.http 16 .post(this.url, { transfer: 100 }) 17 .pipe(concatMap(() => this.http.get("..."))) 18 19 20 21 22 23 } 24
  119. @Component({ selector: "my-app", template: ` {{ amount }} <button (click)="sendMoney()">Send

    $$$</button> `, styleUrls: ["./app.component.css"] }) export class AppComponent { amount: number; url = "https://bank.com/transferMoney"; constructor(private http: HttpClient) {} sendMoney(): void { this.http .post(this.url, { transfer: 100 }) .pipe(exhaustMap(() => this.http.get("..."))) .subscribe((newAmount) => { this.amount = newAmount; alert("transferred successfully") }); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
  120. @Component({ selector: "my-app", template: ` {{ amount }} <button (click)="sendMoney()">Send

    $$$</button> `, styleUrls: ["./app.component.css"] }) export class AppComponent { amount: number; url = "https://bank.com/transferMoney"; constructor(private http: HttpClient) {} sendMoney(): void { this.http .post(this.url, { transfer: 100 }) .pipe(exhaustMap(() => this.http.get("..."))) .subscribe((newAmount) => { this.amount = newAmount; alert("transferred successfully") }); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 .pipe(exhaustMap(() => this.http.get("..."))) @Component({ 1 selector: "my-app", 2 template: ` 3 {{ amount }} 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 amount: number; 10 url = "https://bank.com/transferMoney"; 11 12 constructor(private http: HttpClient) {} 13 14 sendMoney(): void { 15 this.http 16 .post(this.url, { transfer: 100 }) 17 18 .subscribe((newAmount) => { 19 this.amount = newAmount; 20 alert("transferred successfully") 21 }); 22 } 23 } 24
  121. @Component({ selector: "my-app", template: ` {{ amount }} <button (click)="sendMoney()">Send

    $$$</button> `, styleUrls: ["./app.component.css"] }) export class AppComponent { amount: number; url = "https://bank.com/transferMoney"; constructor(private http: HttpClient) {} sendMoney(): void { this.http .post(this.url, { transfer: 100 }) .pipe(exhaustMap(() => this.http.get("..."))) .subscribe((newAmount) => { this.amount = newAmount; alert("transferred successfully") }); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 .pipe(exhaustMap(() => this.http.get("..."))) @Component({ 1 selector: "my-app", 2 template: ` 3 {{ amount }} 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 amount: number; 10 url = "https://bank.com/transferMoney"; 11 12 constructor(private http: HttpClient) {} 13 14 sendMoney(): void { 15 this.http 16 .post(this.url, { transfer: 100 }) 17 18 .subscribe((newAmount) => { 19 this.amount = newAmount; 20 alert("transferred successfully") 21 }); 22 } 23 } 24 .subscribe((newAmount) => { this.amount = newAmount; alert("transferred successfully") }); } @Component({ 1 selector: "my-app", 2 template: ` 3 {{ amount }} 4 <button (click)="sendMoney()">Send $$$</button> 5 `, 6 styleUrls: ["./app.component.css"] 7 }) 8 export class AppComponent { 9 amount: number; 10 url = "https://bank.com/transferMoney"; 11 12 constructor(private http: HttpClient) {} 13 14 sendMoney(): void { 15 this.http 16 .post(this.url, { transfer: 100 }) 17 .pipe(exhaustMap(() => this.http.get("..."))) 18 19 20 21 22 23 } 24