Reputation: 40896
I'm trying to write a DataResolver
service that will allow the Angular 2 router to preload data before initializing my component.
The resolver needs to call different API endpoints to fetch data appropriate to the route being loaded. Rather than having a resolver for each of my many components, I'm building one generic resolver. Thus, I'd like to pass custom input in the route definition that points to the correct endpoint. For instance, consider these routes:
app.routes.ts
appRoutes = [
{
path: 'project/:id',
component: ProjectComponent,
resolve: { data: DataResolver }
},
{
path: 'store/:id',
component: StoreComponent,
resolve: { data: DataResolver }
}
]
In the first instance, the resolver will need to call /path/to/resource1/id
. In the second case, /path/to/resource2/id
. Ideally, I would pass the endpoint as an argument in the route definition that would then be available in the DataResolver
constructor.
Can this be done with a generic resolver class?
Angular 2.0.1
written in Typescript 2.0.3
Upvotes: 20
Views: 24530
Reputation: 1
You can get the id as the following snippet:
class DataResolve implements Resolve<string> {
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
console.log(parseInt(route.paramMap.get('id'), 10))
}
}
Please notice that type of route.paramMap.get('id') will be string.
Upvotes: 0
Reputation: 1871
This answer solved my problem, but I also needed this to be applied in case the route has multiple resolvers.
eg.
{
path: 'transactions/showcase/edit/:id',
component: ClientsTransactionsFormComponent,
resolve: {
clients: Resolver,
clientTransaction: Resolver,
clientTransactionTypes: Resolver
},
In that case I solved my issue by passing an array in data.
data: ['Clients/GetAll', 'ClientTransactions/GetByID/', 'ClientTransactionTypes/GetAll']
and also modified my resolver like this..
resolve(route: ActivatedRouteSnapshot) {
let row = [];
let id = "";
Object.keys(route.data).forEach(e => {
row.push(route.data[e]);
})
let path: string = row[0];
delete row[0];
route.data = row;
if (path.lastIndexOf('/') == path.length - 1) {
id = route.params['id'];
}
return this._httpService.httpGet(this.baseUrl + path + id);
}
hope it helps anybody.
Upvotes: 4
Reputation: 208994
I don't know about making it available in the constructor, without using DI. But if you want it available in the resolve
method, you could just add a data
property in the route definition, and this would make it available to the ActivatedRouteSnapshot
{
path: 'project/:id',
component: ProjectComponent,
resolve: { data: DataResolver },
data: { path: 'project/:id' }
}
class DataResolve implements Resolve<string> {
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
return route.data['path'];
}
}
Upvotes: 34