Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Secondary child outlet inside empty primary segment does not match #14662

Closed
ddavid67 opened this issue Feb 23, 2017 · 12 comments
Closed

Secondary child outlet inside empty primary segment does not match #14662

ddavid67 opened this issue Feb 23, 2017 · 12 comments

Comments

@ddavid67
Copy link

ddavid67 commented Feb 23, 2017

I'm submitting a ... (check one with "x")

[X] bug report
[ ] feature request
[ ] support request

Current behavior
A secondary child named outlet inside an empty primary outlet does not match.

Expected behavior
A secondary child named outlet inside an empty primary outlet should match.

Minimal reproduction of the problem with instructions
http://plnkr.co/edit/O4XNG3FHhWM0m1XRwX0p?p=preview

Just click on link "show bar in secondary outlet".
Going to http://.../(foo:bar) does not init the Bar component inside the foo named router-outlet
Going to http://.../(foo:bar) should init Bar component inside the foo named router-outlet

What is the motivation / use case for changing the behavior?

Please tell us about your environment:

  • Angular version: 4.0
  • Browser: [all]
  • Language: [all | TypeScript X.X | ES6/7 | ES5]
@ddavid67 ddavid67 changed the title Secondary outlet inside empty primary segment does not match Secondary child outlet inside empty primary segment does not match Feb 23, 2017
@ddavid67
Copy link
Author

can someone take a look at my plunker, and at least tell me if I am doing something wrong ?

@denisyilmaz
Copy link

i think our issues are the same. #14896 any updates on this?

@bennadel
Copy link

bennadel commented Oct 4, 2017

Yeah, I'm definitely running into this as well. I have a named-outlet that is a sibling to a primary outlet, both of which are inside a pathless wrapper component: https://plnkr.co/edit/4sKU9I9YurG05Kmv4H0l

I thought it might be this issue: #18271

... not sure which is more accurate.

@Meligy
Copy link
Contributor

Meligy commented Oct 4, 2017

I also can confirm this issue, using @bennadel example.

Take a look at this config:

    RouterModule.forRoot(
      [
        {
          path: "",
          component: StandardLayout,
          children: [
            {
              path: "layout-a",
              component: LayoutA
            },
            {
              path: "layout-b",
              component: LayoutB
            },
            {
              outlet: "widget", // <---- This is the named outlet.
              path: "thing",
              component: Widget
            }
          ]
        }
      ])

When you add a have the named router outlet and a router link inside StandardLayout component like

<a [routerLink]="[{ outlets: { widget: [ 'thing' ] } }]">Open Widget</a>
<router-outlet name="widget"></router-outlet>

And you click the link, you get

Error: Cannot match any routes. URL Segment: 'thing'

This is reproducible here: https://stackblitz.com/edit/angular-khsgga?file=app%2Fapp.module.ts


Now, take that thing named outlet route outside of the empty path route, like:

    RouterModule.forRoot(
      [
        {
          outlet: "widget", // <---- This is the named outlet.
          path: "thing",
          component: Widget
        },
        {
          path: "",
          component: StandardLayout,
          children: [
            {
              path: "layout-a",
              component: LayoutA
            },
            {
              path: "layout-b",
              component: LayoutB
            },
          ]
        }
      ])

When you try again (make sure to reset the URL to / in the browser every time you test this, to avoid false results), and click that link, you get:

  • No error
  • Nothing showing (nothing filling the named outlet)

The reason for nothing showing is that now because the named outlet route is top level, we can not put the named router-outlet tag inside StandardLayout component anymore. We have to put it top level (in AppComponent), which breaks the original use case of using it inside the StandardLayout component route (the one with empty path here), with either of its child routes setting the named outlet route as they wish.

A working case can be shown at: https://stackblitz.com/edit/angular-qas6hg?file=app%2Fapp.module.ts

In this particular example, I can remove StandardLayout component completely, put its content in the AppComponent directly, and promote its children as top-level routes). But remember:

  • This is just a demonstration. Any real world scenario of this case may not be achievable. It's also bad in case I need AppComponent for anything else (general nav or whatever). It's not clean.
  • The functionality is still broken, whereas the functionality is routing to named outlet as a child of a route with empty string path.

P.S.

I can also confirm that moving the route and its router-outlet tag under a non-empty-path (like layout-a in the example above) does work, so, it's not that the named outlet needs to be top level, it just doesn't work when inside (a child of) an empty path route.

Example: https://stackblitz.com/edit/angular-yshtrh?file=app/app.module.ts

@Meligy
Copy link
Contributor

Meligy commented Oct 4, 2017

As @bennadel mentioned on Twitter, another workaround is to prefix the entire app routes, something like:

    RouterModule.forRoot(
      [
        {
          path: "",
          pathMatch: "full",
          redirectTo: "app" // <-- prefix
        },
        {
          path: "app", // <-- prefix
          component: StandardLayout,
          children: [
            {
              path: "layout-a",
              component: LayoutA
            },
            {
              path: "layout-b",
              component: LayoutB
            },
            {
              outlet: "widget", // <---- This is the named outlet.
              path: "thing",
              component: Widget
            }
          ]
        }
      ])

A silly side effect of that is that all routes have to include the prefix if they are root-relative, or change to be relative to current route, like:

      <a routerLink="./layout-a">Layout A</a> |
      <a routerLink="/app/layout-b">Layout B</a>

Working example showing this: https://stackblitz.com/edit/angular-hdhh8a?file=app/app.module.ts

Reproducing the issue

This prefix example also makes it super easy to reproduce the issue, just try the sample, remove the prefix "app", and click on the link "Open Widget" to see it break with empty path.

@bennadel
Copy link

bennadel commented Oct 4, 2017

@Meligy very excellent! Thanks for putting that together -- I was gonna try after work.

@bennadel
Copy link

bennadel commented Oct 5, 2017

It looks like this bug manifests if the parent segment is pathless, even if there is an ancestor with a path. For example, this still breaks:

{
    path: "app",
    children: [
        {
            path: "", // <---- direct parent is empty, even through there is a non-empty ancestor.
            component: StandardLayout,
            children: [
                {
                    path: "layout-a",
                    component: LayoutA
                },
                {
                    outlet: "widget", // <---- will not work
                    path: "widget",
                    component: Thing
                }
            ]
        },
        {
            path: "console",
            component: ConsoleLayout,
            children: [
                // ....
            ]
        }
    ]
}

Even though the entire route-set is wrapped in the prefix /app, the named-outlet will still break because its local parent segment is empty. So, it's not just the route can't be empty, it's that the direct parent can't be empty.

@wdumlao
Copy link

wdumlao commented Dec 20, 2017

Is this issue fixed with the latest router package?

@TGC79
Copy link

TGC79 commented Jan 23, 2019

Caused by #10726 which should be reopened since the fix for it was reverted.

Issue was first reported on Angular 2.0.0-rc.5.

@DaSchTour
Copy link

This is still an issue. Don't close this like #10726

@atscott
Copy link
Contributor

atscott commented May 26, 2020

Duplicate of #10726, which is reopened now.

@angular-automatic-lock-bot
Copy link

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 Jun 26, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

10 participants