```typescript import { EventEmitter, Injectable, } from '@angular/core'; import { CanActivate, Routes, Router, RouterStateSnapshot, UrlSegment, } from '@angular/router'; /* * This service interacts with the WordPress' API to get content (routes) */ import { BackendService } from './backend.service'; @Injectable() export class PageRouteService implements CanActivate { private _routes: Routes; constructor( private _backend: BackendService, private _router: Router, ) { this._routes = []; } /* * THE GOODS */ /* * Load and use dynamic routes for pages as a `canActivate` route guard * * Reset Router config with Routes built for pages provided by backend data. * If NOT routing to home, interrupt routing and reload the original request * with the updated routes. Otherwise, when routing to home, we still need to * reset with updated Routes to prime for `routerLink`-based navigation, but * we have the route we need; we don't need to reload before proceeding with * routing (so we return 'true'). */ canActivate(state: RouterStateSnapshot): Promise { let isHome: boolean; isHome = '/' === state.url; let canActivatePromise: Promise; canActivatePromise = new Promise((resolve) => { // If home, resolve immediately if (isHome) { resolve(true); } // Helper that knows how to get data from BackendService this._fetchPageRouteDataFromBackend() .then((routeData: Array<{page_path: string}>) => { // Get current router config let routes: Routes; routes = this._router.config; // Add routes to beginning of routes config array // // This helper function knows structure of both page data from BackendService, // and the format the Angular router config needs. for (let route of this._constructPageRoutesFromPageArray(routeData)) { routes.unshift(route); } // Reset router with modified routes this._router.resetConfig(routes); // Indicate we are now ready this._updateStatus('ready'); if (! isHome) { // interrupt navigation and reload with updated routes resolve(false); // Retry original request with updated routes, without adding a redirect step to browser history this._router.navigateByUrl(state.url, { replaceUrl: true }); } }); }); return canActivatePromise; } /* * Construct routes from an array of page data */ private _constructPageRoutesFromPageArray(pages: {page_path: string}[]): Routes { let routes: Routes; routes = []; for (let page of pages) { let route = { path: page.page_path, component: PageComponent, data: { page_path: page.page_path } }; routes.push(route); } return routes; } } ```