Adding routes dynamically to lazy loaded modules in Angular
The project I am working on consist of a lot of master detail pages. Most of these have an shared attachment component as common detail page. So I faced the following challenge: “How do you add a generic children route in hundreds of routes in multiple lazy loaded modules?”.
Manual entry is not a desirable option and although all routing modules eventually will be generated based on a meta driven model, still I didn’t like the idea of seeing this particularly route repeated over and over again.
I needed a way to add these dynamically to the route configuration. After fiddling with some idea’s from Stack Overflow I found the solution that worked for me and may help you as well. Because of limited control it’s a bit of a hack.
The following two problems are solved:
- Lazy loaded modules : The router config can only be changed after the module is loaded.
- Deep-linking : When the router starts to navigate to the URL it just does not exists yet.
Code example lazy loaded
Lazy loading of a module can be detected by subscribing to the RouteConfigLoadEnd router event. This event will be triggered after a module is lazy loaded.
The method addDynamicPath will try to add the route to the module, if successful the router will be reset with the altered config. (UPDATED -> Don’t reset the router)
This part it tricky, first the change detection needs to be triggered, otherwise the private _loadedConfig attribute will be undefined. (There is no other way to access the private attribute, and this is the only way that I know of to alternate the module routes). With some trial and error the right routes can be found and modified. In this case the master route is marked with data so this algorithm knows which route needs a child route.
Code example deep-linking
I could not find a way to freeze the router from its navigation cycle so the code in the lazy loaded section would be ready and the route would be known. If you do, please tell me! So the only solution is to catch this unknown route before its redirected to the 404 page. This is done with an canActivate guard.
It catches the specific route by last url segment, in this case “dynamic”. Because of this route the module is lazy loaded and the dynamic route will be inserted. Only problem is that change detection needs to be triggered before new route is known. Then a redirect will work. If this change detection is not triggered an endless redirection loop will fire. All other unknown routes will just be redirected to 404.
Stackblitz code demo
Navigate with the buttons to the general module and then to the dynamic route for the normal dynamic insertion then hit refresh in the StackBlitz browser for the deeplink