angular: Lazy loaded module in named outlet throws error

[x] bug report [ ] feature request [ ] support request

Current behavior Navigating to route with lazy loaded module in named outlet throws error:

Uncaught (in promise): TypeError: Cannot read property ‘routes’ of undefined

Expected behavior Navigating to route with lazy loaded module in named outlet without errors.

Minimal reproduction of the problem with instructions When I have configured my routes with named outlet and want to have lazy loaded module in that outlet.

export const routes: Routes = [
 {  
   path: '',
   component: AppComponent,
   children: [
     {
       path: '',
       loadChildren: "app/home/home.module#HomeModule"
     },   {
       path: '',
       loadChildren: "app/about/about.module#AboutModule",
       outlet: "about"
     }
   ]
  }
];

Here is the plnkr to demonstrate the behavior: http://plnkr.co/edit/nK9kJYdakXILZU0UKFrP?p=preview (Anything is displayed because of error)

What is the motivation / use case for changing the behavior? Using lazy loaded modules in named outlets.

Please tell us about your environment:

Angular version: 2.0.X

Browser: [all | Chrome XX | Firefox XX | IE XX | Safari XX | Mobile Chrome XX | Android X.X Web Browser | iOS XX Safari | iOS XX UIWebView | iOS XX WKWebView ]

Language: [all | TypeScript X.X | ES6/7 | ES5]

Node (for AoT issues): node --version =

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 120
  • Comments: 58 (12 by maintainers)

Commits related to this issue

Most upvoted comments

We have this

    {
        path: 'me',
        outlet: 'hub',
        component: ProxyRouteComponent,
        children: [
            {
                path: '',
                loadChildren: 'hub#HubModule',
            },
        ],
    },

Where proxy route component is simply

import { Component } from '@angular/core';

@Component({
    selector: 'b-proxy-route',
    template: '<router-outlet></router-outlet>',
})
export class ProxyRouteComponent {
}

Though I don’t want to speak on behalf of the Angular team, I feel like something needs to be said here:

This issue doesn’t get closer to resolution in proportion to the number of comments that say “Any update on this”/“Any fix for this”/etc. Thumbs-upping those comments doesn’t magically go into some petition for the Angular team to finish this.

If you’re stuck, read the thread – there’s a workaround, which as the name suggests, will get you working. If you’d like to get updates on this, save some keystrokes by clicking the ‘Subscribe’ button – that allows you to receive updates in your email. You’ll also receive updates every time someone comments “Any update on this?”, so please, don’t be that person.

Better yet, be the change you want to see in the world and submit a pull request.

Hi there, I am also interested to know if we will be able to lazy load secondary routes in the future

I know It’s been a while since commit 8f2fa0f766d9f, but can you @vsavkin remember why you added that “a componentless route cannot have a named outlet set” guard.

Is it because it’s just not possible to lazy load in such a way (because maybe router is designed so) or is this something that will eventually be resolved sometime.

Any update on this ?

Any update on this ?

Any update on this ?

Any update on this ?

There seems to be no update. I get stuck in this.

The happiness was very close.

As stated buy @gmfun, the solution by @UnwrittenFun works. But refreshing make the app crash. So I think this bug should really be addressed soon… Lazy load a module in a name router outlet is quite a common pattern in auxiliary routes…

Is there any information about this issue?? just so I know in my company if we should do a temporary solution until it’s fixed or think about a more permanent solution. I just need an answer to a simple question: “is this planned in the @angular/router team roadmap or not for now??”

What worked for me is two things:

  • Always have an empty-path redirection on all levels.
  • Use the full named-outlet-URL-syntax for redirection.

After hours and hours of debugging this I’m too tired to explain this more clearly, so let me just leave you with an example route-configuration I use here:

export const routes: Routes = [
    {
        path: '',
        redirectTo: '/index/(main:newsfeed//header:newsfeed)', // this is important because there are no cascading redirects, see: https://github.com/angular/angular/issues/10120
        pathMatch: 'full',
    },
    {
      path: 'index',
      component: IndexIndexComponent,
      children: [
        {
            path: '',
            redirectTo: '/index/(main:newsfeed//header:newsfeed)',
            pathMatch: 'full',
        },
        {
            path: 'newsfeed',
            loadChildren: "c/newsfeed-index/newsfeed-index.module#NewsfeedIndexModule",
            outlet: 'main',
        },
        {
            path: 'newsfeed',
            loadChildren: "c/me-header-index/me-header-index.module#MeHeaderIndexModule",
            outlet: 'header',
        },
      ]
    },
  ]

To be honest, while it is super-unintuitive and documentation and examples around this are missing entirely, I guess it actually makes sense that the Angular router would need the specific outlet and route for that outlet specified. …or I’m just too tired and I can’t see how stupid it is that this is necessary.

In any case, I can keep developing my application now… (after some sleep, of course!)

Omg a fix!!! Yessss! I’ll be able to delete soooooo much portal code. Please don’t let this PR die! It needs tenderness and nourishment!

Same issue here, I want to lazy load a module with a path to a named outlet. Cant figure a way to get it to work

Ich kehre zurück am 01.11.2017.

Ich werde Ihre Nachricht nach meiner Rückkehr beantworten. In dringenden Fällen senden Sie bitte eine Kopie Ihrer E-Mail für technische Angelegenheiten an entwicklung@arxes-tolina.de, ansonsten an info@arxes-tolina.de. Ein anderer Mitarbeiter wird sich dann Ihrer E-Mail annehmen.

Hinweis: Dies ist eine automatische Antwort auf Ihre Nachricht “Re: [angular/angular] Lazy loaded module in named outlet throws error (#12842)” gesendet am 23.10.2017 07:17:38.

Diese ist die einzige Benachrichtigung, die Sie empfangen werden, während diese Person abwesend ist.

Unfortunately, the issue is still there. Had to struggle finding workarounds for Angular 7 apps and most lead to switching off the lazy loading.

@atscott Reverted in 8f24bc9. Fails internal tests.

Why should this be a community problem? This is a Google problem. Point. We applied the patch manually to @angular/router and … uhm well it just works. This the reason why Angular is the devil. This project is too dependent on Google’s death star.

Same here, any updates ?

Solution proposed by @UnwrittenFun mostly works, but on refreshing the page with secondary route this throwing error Cannot read property 'routes' of undefined I have tried remove lazy loading { path: "test", component: ModalComponent, outlet: 'modal'},

This is happening if I have a route with path: "" somewhere in app routing, Works fine if I change this to path: "something"

@atscott Reverted in 8f24bc9. Fails internal tests.

Why should this be a community problem? This is a Google problem. Point. We applied the patch manually to @angular/router and … uhm well it just works. This the reason why Angular is the devil. This project is too dependent on Google’s death star.

If a change to Angular causes any consumer’s tests to fail, then it’s a backwards-incompatible change and needs to be reverted, or at the very least only included in a new major release with suitable warnings around it. In this case, Google just happens to be a high-value consumer of the library. The fact that their tests caught an issue before it made it into a release candidate is good for other consumers like us. See discussion on this topic on the PR #38379.

There’s a separate argument to be made that it might be helpful to describe the cause of the test failures publicly, so that non-Google contributors could help with the fix, but that discussion is already happening on the PR and it seems like Google does intend to circle back with that information when they’ve identified the root cause.

O.M.G… I just waste so much time to search why my lazy loading routing outlet was not working … I followed @nasreddineskandrani to “fix” it.

The above change (by me) seems to fix it for me though, cheers.

I think the error cannot read property 'routes' of undefined is for the primary outlet. I had the same issue on refresh, so I had to specify a route for the primary outlet as well:

this.router.navigate([{ outlets: { primary: [ 'home' ], modal: [ 'login' ] } }], { skipLocationChange: true });

doing

this.router.navigate([ '/home', { outlets: { modal: [ 'login' ] } }], { skipLocationChange: true });

didn’t throw the error, but it didn’t populate the named router outlet

I am facing same issue with unnamed router-outlet with Lazy Loaded Module. It throws same error

Uncaught (in promise): TypeError: Cannot read property ‘routes’ of undefined

Any fix for this?

Any update on this?

Any update on this?

@atscott can you please explain why this fix is listed in the change log for 10.1.0 but this issue is still open and I don’t think the PR was merged. Is this is a mistake?

https://github.com/angular/angular/blob/master/CHANGELOG.md

“router: support lazy loading for empty path named outlets”

Yes, that’s a mistake. The commit was reverted because we found an issue after it went in. I’ve since investigated the failure more and reworked the solution. I plan to merge the change next week and it’ll go into the 11.0.0-next.1 release.

Would you like to send a PR to correct the changelog?

Given the issue created 13 Nov 2016, that’s not a temporary workaround.

Ok I resolved my problem. A full example of module lazy loaded displayed in a named router outlet is available here --> https://github.com/mchavaillaz/angular-router-named-outlet-lazy-loaded.

Yes, will do.

@atscott can you please explain why this fix is listed in the change log for 10.1.0 but this issue is still open and I don’t think the PR was merged. Is this a mistake?

https://github.com/angular/angular/blob/master/CHANGELOG.md

“router: support lazy loading for empty path named outlets”

A temporary workaround would be to use the preloadingStrategy.

@NgModule({
  imports: [
    RouterModule.forRoot(routes, {
      preloadingStrategy: PreloadAllModules,
    }),
  ],
  exports: [RouterModule],
})

@molcik @maxime1992 I created PR with my own fix for that issue, may you please review it?

Found a PR that fixes it.

And I’ve written a comment to show how to apply that patch locally…

Other than that nop 🤷‍♂️

@UnwrittenFun I tried the solution you posted and it is not working in this stackblitz online example maybe i did something wrong?

Steps to reproduce the issue in my online example:

if you uncomment app.module.ts line 39 it breaks with the error as he mentions in the initial post issue

Uncaught (in promise): TypeError: Cannot read property ‘routes’ of undefined

My example is the same as the initial issue post (empty path everywhere => and no! naming the route is not an option)

note: bug present in Angular v7 (i didn’t try to solve it with ivy and maybe it is possible with lazy loading of components)

TODO

Someone needs to try https://github.com/angular/angular/pull/25585 to see if it works and doesn’t create regression somewhere else.

Possible solution/workaround

I found a solution without the router to lazy load => by doing it manually https://github.com/nasreddineskandrani/example-lazyload-header-conditionally check the readme file to access the article i used to build this solution (this is not working on stackblitz so i can’t post it online)


If you have a solution/workaround please fork my online example and repost it working -> in other case i suggest highly to stop polluting the thread with unrelated cases and open new issues (my 2 cents).

Great @SvenSchoene! It make sense to me. I’ve reached some situations where an empty-path was necessary to handle with secondary routes. I think you found the answer more clearly: secondary routes - or named outlets - need a path specified (in this case, an empty path) to the primary outlet .