5

Im looking for a way to use one angular route resolve to use on all of my routes, but with different parameters:

currently, i have something like:

   {
        path: 'user/:any',
        component: UserprofileComponent,
        resolve: { ProfiledUser: UserprofileResolver }
      },

profileuser resolve:

 resolve(route: ActivatedRouteSnapshot) {
    return this.GlobalService.Get('/userprofile/admin');
  }

Im in fact looking for a way to use the parameters the Get function from GlobalService is using, for the resolver itself.

I have made something previously that could in theory work:

  path: 'family/panel',
        component: FamilyCoreComponent,
        canActivate: [PermissionGuardService],
        data: {roles: [0]},

where canactivate permission guard:

  canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot):Observable<boolean>|boolean {

    var requirementRole = next.data.roles[0];

So my question is, should i use the principle for the resolver, as i did to my permission guard?

For example something like:

  {
    path: 'user/:any',
    component: UserprofileComponent,
    resolve: { ProfiledUser: UserprofileResolver }
    data: {load: 'userprofile/admin'},
  },

Would this be a good way to do it? if so, how would i do it to make this the most efficient?

maria
  • 207
  • 5
  • 22
  • 56
  • Check this Medium article which as a pretty good example of how to use a resolver and how to reuse the component as subcomponent as well: https://medium.com/@santibarbat/reuse-angular-component-with-resolver-as-subcomponent-in-your-template-762ba1e7d81c?source=friends_link&sk=0540ef11efdcae44c0b7b21c177d5e06 – Santi Barbat May 09 '20 at 12:13

1 Answers1

1

great question, made me scratch my head for quite some time too :).

So let's dive in my solution for this problem.

When using Resolver we have the ability to replace the resolver with anything we like (functions/classes).

@NgModule({
  imports: [
    RouterModule.forRoot([
      {
        path: 'team/:id',
        component: TeamComponent,
        resolve: {
          team: 'teamResolver'
        }
      }
    ])
  ],
  providers: [
    {
      provide: 'teamResolver',
      useValue: (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => 'team'
    }
  ]
})

This snippet comes straight from the ng Docs

So in your case, you are able some extra parameters in the useValue line, like this

useValue: (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) =>
  new ResolverWithParamsResolver(
          route,
          state,
          "customLink"
      ).resolve()

And your ResolverWithParamsResolver you might have, something like the following code snippet

export interface ResolverWithParamModel<T> {
  resolve(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot,
    linkParam: string
  ): Observable<T> | Promise<T> | T;
}
// Custom resolver
@Injectable()
export class ResolverWithParamsResolver implements ResolverWithParamModel<any> {
  constructor(
    private route: ActivatedRouteSnapshot,
    private state: RouterStateSnapshot,
    private linkParam: string
  ) {}

  resolve(): Observable<any> | Promise<any> | any {
    return of(this.linkParam)
  }
}

So now you will have access to your linkParam.

Here is a demo, which is a bit more complex than the snippets in the answer, that implements the desired effect.

Note:

If I have 10 to 15 possible different configurations for the custom resolver, I would probably create 10-15 resolvers, as it will be easier to understand from the first glance what does each resolver do.

Disclaimer:

Not sure if this is the best solution, but I think something along these lines is the thing that you desire, if you meet any trouble with the implementation, please create a stackblitz/codesandbox/plunker demo and I will do my best to help you :)

  • 1
    Same idea, it's at best to create multiple resolver. Verbose and easy to understand, also if there is one route/module get a major refactoring, you will change the resolver for that specific area only. – trungk18 Jul 11 '19 at 07:12
  • I'm not sure if thats fully cover what OP was asking for. I am actually missing one key point here - how to use subsequent resolved values in `TeamComponent`. I tried to subscribe to "activatedRoute.data" yet for after navigating to other route and back, the subscription no longer provides values. Probably this is separate question - I'll continue to look for other questions and possibly write my own. – ciekawy Oct 14 '20 at 14:26
  • well actually I just found out having proper routing set up the `activatedRoute.data` emits newly resolved values as it should (possibly via `advanceActivatedRoute` from `router-state`. – ciekawy Oct 14 '20 at 16:18