Given the following route:
path: \'\',
component: MyComponent,
resolve: {
foo: FooResolver,
bar: BarResolver
}
Is there any way of tell
I tackled this scenario using combineLatest
in a single resolver
. You can do this:
@Injectable({providedIn: 'root'})
export class FooBarResolver implements Resolve<any> {
constructor(
private readonly fooResolver: FooResolver,
private readonly barResolver: BarResolver
) {}
resolve() {
return combineLatest(
this.fooResolver.resolve(),
this.barResolver.resolve()
).pipe(map(([users, posts]) => ({users, posts})))
}
}
I found a slightly more elegant solution that can be used if you don't care about the results from all of the resolvers:
class FooBarResolver implements Resolve<Observable<any>> {
constructor(
protected fooResolver: FooResolver,
protected barResolver: BarResolver
) { }
resolve(): Observable<any>
{
return this.fooResolver.resolve().pipe(
concat(this.barResolver.resolve()),
concat(this.barResolver.resolve())
);
}
}
I use this to trigger the data loading in my services. And because they write the data / isLoading / error into an Akita storage, I don't care about the results of the resolvers.
Resolvers are resolved in parallel. If Foo
and Bar
are supposed to be resolved in series they should be a single FooBar
resolver. If they are supposed to be used by themselves in other routes, FooBar
can wrap Foo
and Bar
resolvers:
class FooBarResolver implements Resolve<{ foo: any, bar: any }> {
constructor(
protected fooResolver: FooResolver,
protected barResolver: BarResolver
) {}
async resolve(route): Promise<{ foo: any, bar: any }> {
const foo = await this.fooResolver.resolve(route);
const bar = await this.barResolver.resolve(route);
return { foo, bar };
}
}
FooBar
should be aware of the fact if it is a promise or an observable that is returned from Foo
and Bar
in order to resolve them properly. Otherwise additional safety device should be added, like await Observable.from(this.fooResolver.resolve(route)).toPromise()
.
FooBar
and Foo
or Bar
shouldn't appear within same route because this will result in duplicate resolutions.
One other option is to wrap your dependent routes and use necessary resolver on wrapper.
I.E.
{ path: '', resolve: { foo$: FooResolver }, children: [
{ path: 'mySubRoute', resolve: {bar$: BarResolver }, component: BarComponent }
]}
*If you meet with relative path resolving problems, try using
relativeLinkResolution: "corrected"
In forRoot router method. More info here Angular RouterLink relative path does not work in component having empty path