12

So my application is based on angular 2(angular cli) and some CMS. Some fragments of page are downloaded from CMS and displayed on angular 2 page. The main problem is that the header and footer are from CMS. So I wonder how to add global resolver(global is very important, I dont want to add resolver for every route path in application), that will force angular to wait till CMS will return header and footer. I am already successfully using resolver to wait for some data on some routes by implementing route interface

export class InboxResolver implements Resolve<MessageListItem[]>

and I am using it in some custom routes:

const MessagesRoutes: Routes = [
 {
    path: 'inbox',
    component: InboxComponent,
    resolve: { messages: InboxResolver }
 }
];

But how to define one global HeaderAndFooterResolver in one place?

VSO
  • 11,546
  • 25
  • 99
  • 187
user2771738
  • 913
  • 11
  • 31
  • As far as I know, doing what you are asking is not possible. One solution is to add a function to the resolver that checks whether or not the data is already loaded - this will at least prevent duplicate calls, you will still need a resolver on every route though. – VSO Dec 06 '16 at 17:39

3 Answers3

15

Not sure what your question is about but you can use a componentless parent route with a resolver and share this with all its child routes

const MessagesRoutes: Routes = [
    { path: '', resolve: { messages: InboxResolver }, children: [
        { path: 'inbox', component: InboxComponent},
        { path: 'xxx', component: XxxComponent},
        { path: 'zzz', component: XxxComponent},
    ]}
];
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • Yup, I am trying something similar like u said. But parent route includes component app.template.component which is using TemplateResolver aka inboxResolver which fetch header and footer from CMS. So to sum up, idea atm is to create app parent route, so every other route must be its child. So this resolver would be resolver for every route in application since every route is child route of app template route – user2771738 Dec 06 '16 at 20:25
  • Yes, every route needs to be a child route of this route, or you add the resolver to each route. – Günter Zöchbauer Dec 06 '16 at 20:28
  • Seems kind of dirty, but I don't have a better solution and it's an idea. Maybe some sort of non-router guard solution? – VSO Dec 07 '16 at 17:22
  • The approach with the resolver on the componentless parent route is a suggestion by the router developer from the Angular team. – Günter Zöchbauer Dec 07 '16 at 17:24
4

You basically need one resolver for each component and need to be declare once for each route, unless they are parent > child, you can share the resolver between them like below:

const MessagesRoutes: Routes = [
  { path: '', resolve: { messages: EmailResolver }, children: [
    { path: 'inbox', component: InboxComponent },
    { path: 'outbox', component: OutboxComponent },
    { path: 'sent', component: SentComponent },
    { path: 'received', component: ReceivedComponent }
  ]}
];
Alireza
  • 100,211
  • 27
  • 269
  • 172
3

Provided you just want to add the resolver to every top level route then something like the below would do it.

   const addGlobalResolver = <T extends Type<Resolve<any>>>(routePaths: Routes, resolver: T, name: string): Routes => {
      return routePaths.map(route => {
        if (route.resolve != null || route.resolve === undefined) {
          route.resolve = {};
        }
        route.resolve[name] = resolver;
        return route;
      });
    };

Just invoke it before you pass the routes to the routing module.

[RouterModule.forRoot(addGlobalResolver(routes, InjuryResolver, 'Injury'))]
garty
  • 406
  • 3
  • 11