Rakhat
Rakhat

Reputation: 4942

Angular 2 router resolve with Observable

After the release of Angular 2 RC.5 there was introduced router resolve. Here demonstrated example with Promise, how to do the same if I make a request to the server with Observable?

search.service.ts

searchFields(id: number) {
  return this.http.get(`http://url.to.api/${id}`).map(res => res.json());
}

search-resolve.service.ts

import { Injectable } from '@angular/core';
import { Router, Resolve, ActivatedRouteSnapshot } from '@angular/router';
import { Observable } from 'rxjs/Observable';

import { SearchService } from '../shared';

@Injectable()
export class SearchResolveService implements Resolve<any> {

  constructor(
    private searchService: SearchService ,
    private router: Router
  ) {}

  resolve(route: ActivatedRouteSnapshot): Observable<any> | Promise<any> | any {
    let id = +route.params['id'];
    return this.searchService.searchFields(id).subscribe(fields => {
      console.log('fields', fields);
      if (fields) {
        return fields;
      } else { // id not found
        this.router.navigate(['/']);
        return false;
      }
    });
  }
}

search.component.ts

ngOnInit() {
  this.route.data.forEach((data) => {
    console.log('data', data);
  });
}

Get Object {fields: Subscriber} instead of real data.

Upvotes: 32

Views: 30817

Answers (1)

G&#252;nter Z&#246;chbauer
G&#252;nter Z&#246;chbauer

Reputation: 657338

Don't call subscribe() in your service and instead let the route subscribe.

Change

return this.searchService.searchFields().subscribe(fields => {

to

import 'rxjs/add/operator/first' // in imports

return this.searchService.searchFields().map(fields => {
  ...
}).first();

This way an Observable is returned instead of a Subscription (which is returned by subscribe()).

Currently the router waits for the observable to close. You can ensure it gets closed after the first value is emitted, by using the first() operator.

Upvotes: 54

Related Questions