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