Skip to content

fix(router): lazy loaded empty root path loads with auxiliary outlet#25483

Closed
attilavegh wants to merge 1 commit intoangular:masterfrom
attilavegh:fix-lazy-loaded-root-with-aux-outlet
Closed

fix(router): lazy loaded empty root path loads with auxiliary outlet#25483
attilavegh wants to merge 1 commit intoangular:masterfrom
attilavegh:fix-lazy-loaded-root-with-aux-outlet

Conversation

@attilavegh
Copy link
Copy Markdown

Initial page load with secondary outlet and lazy loaded root with empty path '/(aux:path)' causes error, because the empty root path is not matched and '_loadedConfig' is undefined. This works fine if the root path is not empty or the root is not a lazy loaded module.

PR Checklist

Please check if your PR fulfills the following requirements:

PR Type

What kind of change does this PR introduce?

[x] Bugfix
[ ] Feature
[ ] Code style update (formatting, local variables)
[ ] Refactoring (no functional changes, no api changes)
[ ] Build related changes
[ ] CI related changes
[ ] Documentation content changes
[ ] angular.io application / infrastructure changes
[ ] Other... Please describe:

What is the current behavior?

Given the following route configuration:

[
    {path: '', loadChildren: 'children'},
    {path: 'a', loadChildren: 'otherChildren', outlet: 'aux'}
]

With this configuration, using the outlet as an entry point to the application, the root module will not load properly and results in the following error:

TypeError: Cannot read property 'routes' of undefined at getChildConfig (router.js:3041)

The _loadedConfig property of the route remains undefined as the expandSegmentAgainstRoute() returns with noMatch().

This issue is only present if the root has a lazy loaded module, works fine with a component or even with a lazy loaded module if the root path is not empty.

Issue Number: N/A

What is the new behavior?

The above mentioned issue is fixed in this pull request, the config is properly loaded and the outlet can be used as an entry point.

Does this PR introduce a breaking change?

[ ] Yes
[x] No

Other information

@googlebot
Copy link
Copy Markdown

We found a Contributor License Agreement for you (the sender of this pull request), but were unable to find agreements for all the commit author(s) or Co-authors. If you authored these, maybe you used a different email address in the git commits than was used to sign the CLA (login here to double check)? If these were authored by someone else, then they will need to sign a CLA as well, and confirm that they're okay with these being contributed to Google.
In order to pass this check, please resolve this problem and have the pull request author add another comment and the bot will run again. If the bot doesn't comment, it means it doesn't think anything has changed.

@googlebot
Copy link
Copy Markdown

CLAs look good, thanks!

Initial page load with secondary outlet and lazy loaded root with empty path '/(aux:path)' causes error, because the empty root path is not matched and '_loadedConfig' is undefined. This works fine if the root path is not empty or the root is not a lazy loaded module
@attilavegh attilavegh closed this Aug 22, 2018
@attilavegh attilavegh deleted the fix-lazy-loaded-root-with-aux-outlet branch August 22, 2018 11:58
@attilavegh attilavegh restored the fix-lazy-loaded-root-with-aux-outlet branch August 23, 2018 12:34
@attilavegh attilavegh reopened this Aug 23, 2018
@giorgiopiatti
Copy link
Copy Markdown

There is any update on this yet?

@maxime1992
Copy link
Copy Markdown

A lot of issues are related to that #10981 #26672 #13807 and this issue has been around for +2 years. If someone could review that MR that'd be fantastic 🙏

@WillEllis
Copy link
Copy Markdown

I'd appreciate this fix being merged too! 👍

@Ilya93
Copy link
Copy Markdown

Ilya93 commented Dec 30, 2018

This fix would be fantastic 🙏

@ngbot ngbot bot added this to the needsTriage milestone Jan 24, 2019
@BACordes
Copy link
Copy Markdown

When the estimated time this fix will come? I'm in need of this fix and don't want to edit the packages myself due to wanting future fixes.

@maxime1992 maxime1992 mentioned this pull request May 23, 2019
@maxime1992
Copy link
Copy Markdown

We do not want to change all of our empty routes and we still need that functionality.
So I've decided to create a patch and apply it directly into the node_modules code...

Even though it's faaar from being ideal, I can't help to think that it might be useful for others so use this with caution ⚠️ but here it is:

  1. Create a postinstall hook within your package.json scripts attribute: "postinstall": "patch -p1 --forward < patches/patch-angular-router.diff || true"

  2. Create a folder patches at the root of your projects

  3. Create the following file

diff --git a/node_modules/@angular/router/fesm5/router.js b/node_modules/@angular/router/fesm5/router.js
index 5cd391e..ce5eccf 100755
--- a/node_modules/@angular/router/fesm5/router.js
+++ b/node_modules/@angular/router/fesm5/router.js
@@ -2513,7 +2513,7 @@ var ApplyRedirects = /** @class */ (function () {
         return segments.length === 0 && !segmentGroup.children[outlet];
     };
     ApplyRedirects.prototype.expandSegmentAgainstRoute = function (ngModule, segmentGroup, routes, route, paths, outlet, allowRedirects) {
-        if (getOutlet(route) !== outlet) {
+        if (getOutlet(route) !== outlet && !isLazyRootWithEmptyPath(route)) {
             return noMatch(segmentGroup);
         }
         if (route.redirectTo === undefined) {
@@ -2809,6 +2809,9 @@ function isEmptyPathRedirect(segmentGroup, segments, r) {
     }
     return r.path === '' && r.redirectTo !== undefined;
 }
+function isLazyRootWithEmptyPath(route) {
+    return !!route.loadChildren && route.path === '' && getOutlet(route) === PRIMARY_OUTLET;
+}
 function getOutlet(route) {
     return route.outlet || PRIMARY_OUTLET;
 }

@DaSchTour
Copy link
Copy Markdown

Is there anything that can be done to speed things up?

@lawrencejob
Copy link
Copy Markdown

Indeed - if there's anything the community can do to help this move ahead, please let us know.

We have a set of huge apps with some horrible janky router workarounds we'd love to remove. Somehow encountered this issue with nearly every Angular app I've ever worked on.

Thanks so much for the PR, by the way, @attilavegh !

@joselcvarela
Copy link
Copy Markdown

joselcvarela commented Jun 17, 2019

Seems this bugfix is really needed. I went to this issue too.
Could someone review this? :/

Edit:
Seems this did not cover my use case since I edited the file .../node_modules/@angular/router/fesm5/router.js with this changes, but still have an issue here:

function getChildConfig(route) {
    if (route.children) {
        return route.children;
    }
    if (route.loadChildren) {
        return route._loadedConfig.routes; // <- Cannot read property 'routes' of undefined
    }
    return [];
}

Edit2:
Also seems not to work with named paths (with outlet option). When I use named paths, did not resolve to any route

@joselcvarela
Copy link
Copy Markdown

joselcvarela commented Jun 18, 2019

I have being debugged this at @angular/router level and I found that here:

concatAll(), first((s: any) => !!s), catchError((e: any, _: any) => {

is calling this:
return childConfig$.pipe(mergeMap((routerConfig: LoadedRouterConfig) => {

So since first(function(s) { return !!s; }), will be called on first truthy value, which means other matched routes will not be executed.
I am trying to implement a fix on this but it's being hard since I am not very familiar with the structure.
@jasonaden @matsko @IgorMinar do you have any ideia on how to fix this?

Edit:
If we comment this if block

if (getOutlet(route) !== outlet) {
return noMatch(segmentGroup);
}

and put a delay(100) between concatAll and first here:
concatAll(), first((s: any) => !!s), catchError((e: any, _: any) => {

seems to work

Edit2:
The delay after concateAll workaround could be related with this
Be wary of backpressure when the source emits at a faster pace than inner observables complete! found here https://www.learnrxjs.io/operators/combination/concatall.html#

@asvishnyakov
Copy link
Copy Markdown

Any updates on this?

@asvishnyakov
Copy link
Copy Markdown

asvishnyakov commented Sep 7, 2019

@matsko @mhevery May anyone from angular correctly implement this fix?

@asvishnyakov
Copy link
Copy Markdown

@attilavegh I created my own PR with for that problem because your doesn't fix issue in case like this:

  {
    path: '',
    outlet: 'footer',
    component: LinksBarComponent
  },
  {
   path: '',
   loadChildren: () => import('./modules/main/main.module').then(m => m.MainModule)
  },

@joselcvarela Thank you very much! Your comment gave me right direction

@dottodot
Copy link
Copy Markdown

dottodot commented Oct 8, 2019

@asvishnyakov So will this fix the following issue

In my app-routing i have

  {
    path: 'cookie',
    outlet: 'popup',
    component: CookieLawComponent
  },

and if I try loading the site directly using https://localhost:4200/(popup:cookie) it throws an error of

zone-evergreen.js:797 Uncaught Error: Uncaught (in promise): TypeError: Cannot read property 'routes' of undefined
TypeError: Cannot read property 'routes' of undefined

@asvishnyakov
Copy link
Copy Markdown

@dottodot It should

@DenysVuika
Copy link
Copy Markdown
Contributor

DenysVuika commented Nov 28, 2019

We are too having this nasty TypeError: Cannot read property 'routes' of undefined problem with the Router and lazy loading with outlet.

Can someone from the Angular team comment on whether this PR is going to be merged during our lifetime?

@ibrcic
Copy link
Copy Markdown

ibrcic commented Dec 10, 2019

This issue was originally reported more than 3 years ago in Angular 2.0.0-rc.5. It was marked as critical more than 2 years ago, and still we have no idea if fix for it is even planned?
I know that Angular team has been pretty busy with Ivy and all, but still, an update would be nice.

@atscott
Copy link
Copy Markdown
Contributor

atscott commented Aug 5, 2020

Closing for a couple reasons:

@atscott atscott closed this Aug 5, 2020
@angular-automatic-lock-bot
Copy link
Copy Markdown

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 5, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.