Search code examples
angularrestroutesrouteconfig

Angular load routing from REST service before initialization


I am looking into the possibility for Angular 8 to dynamically create the routing from a REST service. This idea is that a user can create pages which should be available for access by routing on the web page.

I have seen options to dynamically add routes, however I would like to have the routes loaded before the rest of the app, so that when a user would access: 'website/generatedPage' the routing is in place before the app is fully loaded.

How do I make sure the routes from the REST service are in place before the app continues with the routing options?

The following piece of code adds the routing to late:

    constructor(
    private sitemapService: SitemapService,
    private router: Router
) {
    this.sitemapService.getSiteMap().then(result => {
        result.forEach(sitemapItem => {
            this.router.config.push({ path: sitemapItem.pageName, component: PageComponent });
        });
    });
}

With this code you can navigate to the page when the app is aready loaded, however, when you would directly request the route, it is not loaded yet.

Thank you in advance!


Solution

  • Ok, so I had this exact same issue and I was actually going to use your "solution" when I stumbled up on these three articles and used a combination of them to come up with the solution.

    References:

    https://long2know.com/2017/11/angular-dynamic-routes-and-application-initialization/ https://medium.com/codegg/pre-loading-user-specific-routes-in-angular-ce829430e1cb https://www.tektutorialshub.com/angular/angular-how-to-use-app-initializer/#where-to-use-app-initializer

    My use case: I need to create routes based on a GET response

    Here's what worked for me:

    1. First, I created a new app-init service:

    
    import { Injectable } from '@angular/core';
    import { Router } from '@angular/router';
    
    @Injectable()
    export class AppInitService {
    
      constructor(private Router: Router) {}
    
      init() {
        return new Promise<void>((resolve, reject) => {
    
            // Simple example from an array. In reality, I used the response of
            // a GET. Important thing is that the app will wait for this promise to resolve
            const newDynamicRoutes = ['bulbasaur','charmander','squirtle']
            const routes = this.Router.config;
    
            newDynamicRoutes.forEach(routeName => {
              routes.push({ path: routeName, component: <YourComponent> });
            });
    
            this.Router.resetConfig(routes);
            resolve();
        });
      }
    }
    

    2. Then, I use it in app.module.ts with APP_INITIALIZER

    import { NgModule, APP_INITIALIZER } from '@angular/core';
    import { AppInitService } from './services/app-init/app-init.service'; // New service that I created
    
    ...
    
    export function initializeApp(appInitService: AppInitService) {
      return (): Promise<any> => { 
        return appInitService.init();
      }
    }
    
    ...
    
      providers: [
        AppInitService,
        {
          provide: APP_INITIALIZER,
          useFactory: initializeApp,
          multi: true,
          deps: [AppInitService]
        }
      ],
      bootstrap: [AppComponent]
    })
    export class AppModule {}
    

    This works like a charm. It lets me create routes based on the response from an API.