Reputation: 4263
I know how to create multiple resolve classes for a route but I don't know how to pass the result of one resolve to another resolve.
// Example Route
{
path: 'book/:id',
component: BookComponent,
resolve: {
document: BookResolve,
title: BookTitleResolve
}
}
If the BookResolve returns a book object, how can you pass that book object to the BookTitleResolve?
I have a title service that looks for the key title in data. I need to be able to generate the book title from the book object. This needs to be dynamic.
Upvotes: 13
Views: 4759
Reputation: 137
First of all, omit document resolver from route and keep only title resolver (last resolver) like this:
// Example Route
{
path: 'book/:id',
component: BookComponent,
resolve: {
title: BookTitleResolve
}
}
then re-write BookTitleResolve as follow:
export class BookTitleResolve implements Resolve<string> {
constructor(
private router: Router,
private bookResolver : BookResolve,
private sampleObservableServise : SampleObservableServise
) { }
// add 'async' to resolve method, so we can call resolvers in turn
// and wait for response before go to next resolver
async resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<string> {
// should convert resolver from observable to promise because of using 'await'
// So, we get bookObject before go to next resolver
const bookObject = await this.bookResolver.resolve(route, state).toPromise().then( res => {
return res;
});
// this is final resolver. Again, we should convert resolver from observable to promise
// because of using 'await'
return await this.sampleObservableServise.toPromise().then(val => {
return val
}, () => {
this.router.navigate(['/']);
return null
})
}
}
In conclusion, we should keep only last resolver in route object, in this case:
title: BookTitleResolve
then by using async/await, call other resolvers one by one in your desire order and use their data.
Upvotes: 2
Reputation: 776
Resolves within the same component run concurrently but resolves in parents will complete before children so the easiest way to achieve this is to create a parent route with the purpose of resolving the book.
{
path: 'book/:id',
resolve: {
document: BookResolve
},
children: [ {
path: '',
component: BookComponent,
resolve: {
title: BookTitleResolve
}
} ]
}
Note that the parent doesn't render a component and the child contains a blank path so despite some added boilerplate, the route should act the same functionally.
Then inside your BookTitleResolve implementation, you can retrieve from the parent route:
class BookTitleResolve {
resolve(route: ActivatedRouteSnapshot) {
// Do something with route.parent.data.document
}
}
Upvotes: 12