0

What I'm doing:

I have an angular resolve guard on my route /work/:slug. I would like to instantly resolve that guard with an Observable of local data, while remote data is being fetched over the network. After the network request is successful, replace that local data with the remote.

Notes:

  • My local data is tombstoneDefault.data which is just a javascript array.
  • I use Observable.from() to wrap my local data.
  • My network request on this.someService.getData() will return an Observable.

Question, How do I chain off of [Observable.from][1] my research leads me to switchMap or how can I accomplish this using different operators in RXJS ?

import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve } from '@angular/router';
import { POST_TABLE as tombstoneDefault } from './work-post.content';
import { Observable } from '[rxjs][1]/Observable';

@Injectable()
export class WorkPostResolve implements Resolve<any> {
  constructor() {
  }

  resolve(route: ActivatedRouteSnapshot): any {
    // get tombstoneDefault data
    // then replace with this.someService.getData(route.params.id)
    return Observable.from(tombstoneDefault.data).filter(post => {
      return post.slug === route.params.slug;
    }).switchMap((result) => { // this errors out
      // this.someService.getData(route.params.id)
    });
  }
}

enter image description here

Armeen Moon
  • 18,061
  • 35
  • 120
  • 233

1 Answers1

2

Return an observable in Resolver that has static data and after that it return dynamic data from BE.

https://plnkr.co/edit/ka6ewGPo1tgnOjRzYr3R?p=preview

  @Injectable()
  export class MyResolver implements Resolve<any> {
    constructor(private router: Router) {
    }

    resolve(route: ActivatedRouteSnapshot): Observable<any> {
      return Observable.of(
        Observable.concat(
          Observable.of('static data'),
          Observable.timer(5000)
            .switchMapTo(Observable.of('dynamic'))
        )
      );
    }
  }

  @Component({
    selector: 'my-cmp',
    template: `my cmp {{obs$ | async}}`
  })
  export class MyCmp {
    obs$;

    constructor(private activatedRoute: ActivatedRoute) {
    }

    ngOnInit(): void {
      this.obs$ = this.activatedRoute.data
        .pluck('group')
        .switchMap(x => x);
    }
  }

  @Component({
    selector: 'my-app',
    template: `
      <div>
        <h2>Hello {{name}}</h2>
        <router-outlet></router-outlet>
        <a routerLink="/path">go path</a>
      </div>
    `,
  })
  export class App {
    name: string;

    constructor() {
      this.name = `Angular! v${VERSION.full}`
    }
  }

  let routes = [
    {
      path: 'path',
      component: MyCmp,
      resolve: {group: MyResolver}
    }
  ];
Julia Passynkova
  • 17,256
  • 6
  • 33
  • 32
  • In your example: The string 'static data' doesn't show first in template: `my cmp {{obs$ | async}}` also getting error like: http://imgur.com/a/9Q4Hh when adding the switch map? – Armeen Moon May 03 '17 at 03:37
  • fixed. it shows now. is my plunker works for u or shows the errors? – Julia Passynkova May 03 '17 at 04:28