14
votes

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

2

2 Answers

29
votes

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'];
  }
}
4
votes

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.