Angular 4 How to return multiple observables in resolver
I found a solution for this issue, maybe will help somebody, so basically I've used forkJoin
to combine multiple Observables and resolve all of them.
resolve(route: ActivatedRouteSnapshot): Observable<any> {
return forkJoin([
this._elementsService.getElementTypes(),
this._elementsService.getDepartments()
.catch(error => {
/* if(error.status === 404) {
this.router.navigate(['subscription-create']);
} */
return Observable.throw(error);
})
]).map(result => {
return {
types: result[0],
departments: result[1]
};
});
};
Now it works correctly, as intended.
You can easily resolve multiple observables using withLatestFrom
.
Here's a working demo in Stackblitz: https://stackblitz.com/edit/angular-xfd5xx
Solution below.
In your resolver, use withLatestFrom
to combine your observables:
import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Library } from '../models/library.model';
import { LibraryBook } from '../models/library-book.model';
import { LibraryService } from '../services/library.service';
import { Observable } from 'rxjs';
import { withLatestFrom } from 'rxjs/operators';
@Injectable()
export class LibraryDisplayResolver implements Resolve<[Library, LibraryBook[]]> {
constructor(
private _libraryService: LibraryService,
) { }
resolve (route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<[Library, LibraryBook[]]> {
const libraryId = route.params['id'];
return this._libraryService.getLibrary(libraryId).pipe(
withLatestFrom(
this._libraryService.getBooksFromLibrary(libraryId)
)
);
}
}
Make sure your resolver is set in your route with an appropriate identifier:
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { LibraryDisplayComponent } from './library-display.component';
import { LibraryDisplayResolver } from '../resolvers/library-display.resolver';
const routes: Routes = [
{
path: ':id',
component: LibraryDisplayComponent,
resolve: {
libraryResolverData: LibraryDisplayResolver
}
},
{
path: '',
redirectTo: '1',
pathMatch: 'full'
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class LibraryDisplayRoutingModule { }
In the receiving component, you can access snapshots of both observables like so:
import { Component, OnInit } from '@angular/core';
import { LibraryBook } from '../models/library-book.model';
import { Library } from '../models/library.model';
import { ActivatedRoute } from '@angular/router';
@Component({
// tslint:disable-next-line:component-selector
selector: 'library-display',
templateUrl: './library-display.component.html',
styleUrls: ['./library-display.component.scss']
})
export class LibraryDisplayComponent implements OnInit {
library: Library;
libraryBooks: LibraryBook[];
constructor(
private route: ActivatedRoute
) { }
ngOnInit() {
this.library = this.route.snapshot.data['libraryResolverData'][0];
this.libraryBooks = this.route.snapshot.data['libraryResolverData'][1];
}
}