angular: Cannot remove outlets from path

I’m submitting a … (check one with “x”)

[x] bug report => search github for a similar issue or PR before submitting
[ ] feature request
[ ] support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question

Current behavior

It seems impossible to navigate to some path and clear any named outlets in the process. Consider this code:

this.router.navigate(['/', { outlets: { secondary: null } });

This does not remove the (secondary:) portion from the path. However this code does remove that segment:

this.router.navigate([{ outlets: { secondary: null } });

In addition this.router.navigateByUrl('/') also works.

Expected behavior

The first code should also work and remove the secondary outlet segment from the path.

Minimal reproduction of the problem with instructions

http://plnkr.co/edit/hFsOdLLr2LCq8cJyOF6R?p=preview

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

The current behavior looks erroneous. I believe there should be an else here which sets children[outlet] to null so it is not initialized later.

Please tell us about your environment:

  • Angular version: 2.4.10

Code in master looks the same as in 2.4.10.

  • 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 ]

All browsers.

  • Language: [all | TypeScript X.X | ES6/7 | ES5] I think it is a framework issue rather than a language one.
  • Node (for AoT issues): node --version =

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 43
  • Comments: 30 (3 by maintainers)

Most upvoted comments

It would be nice to use it with the routerLink directive as well.

<a [routerLink]="['/', { outlets: { secondary: null } }]">Back</a>

Thanks!

FWIW I am using the following as a workaround:

this.router.navigate([{ outlets: { secondary: null } }])
           .then(() => this.router.navigate(['/']));

Can we get an update on this? If the route doesn’t specify an outlet, don’t include it. It shouldn’t be more complicated than that.

Tried this on 9.0.0-next.6 now and it still doesn’t work. Highly annoying as it makes secondary outlets virtually useless.

We used to use navigateByUrl (as the OP mentioned) which clears the route completely.

So instead of doing [routerLink]="['/settings/categories', {outlets: { details: null }}]"; (in template), you’re forced to do a this.router.navigateByUrl('/settings/categories'); programmatically, which will both clear the outlet and navigate.

I’m feeling that the Angular team is digging themselves down a rabbit hole with the router. It is clearly too complex, which is why we’re seeing 1,5 year old bugs still not fixed.

Any updates please ? 21 Mar 2017 - 9 August 2019, still open, on the router feature that doesn’t help me to trust the framework really. 😕

And still present on 5.0.0-beta4… So at this point outlets completely unusable, just thanks to angular team

This is still broken @5.2.0. Any news on this issue?

For info, as this core feature still doesn’t work properly, I did as many people suggested me in meetups and talks, to go without the router module, with a custom solution. I don’t like it because it’s a bit less clean code (on my point of view) but at least it works and I can trust this system.

Is this going to be fixed? We have same issue in our project. router.navigate() works of course, but we lose advantages of routerLink, because we can’t use open in a new tab feature easily. Especially with mouse wheel click or context menu option… Need to do hacks because of this.

Also can not clear outlets from routerLink:

[routerLink]=['/', 'path', 1, {outlets: {popup: null}}]

I’m using a named outlet to display a model dialog. So let’s say my current route is:

 /store/products(popup:dialog/faq)

To clear the named route with an explicit navigation this works - in Angular 9.0.0:

 router.navigate( [ { outlets: { 'popup': null }} ] );

createUrlTree tricks

Getting a URL with createUrlTree was a bit tricker.

I just wanted to create a new URL string relative to the current path - but remove all named outlets.

// this retains named outlets, which is fine if that's what you want:
this.router.createUrlTree([ 'dogfood' ], { relativeTo: this.activatedRoute }).toString()
"/store/products/dogfood(popup:dialog/faq)"

// this does NOT work and does not clear the named outlet
this.router.createUrlTree([ 'dogfood', { outlets: { 'popup': null }} ], { relativeTo: this.activatedRoute  }).toString();
"/store/products/dogfood(popup:dialog/faq)"

// frustratingly this does actually makes things worse and you end up with TWO named outlets!
this.router.createUrlTree([ 'dogfood', { outlets: { 'popup': '123' }} ], { relativeTo: this.activatedRoute   }).toString();
"/store/products/dogfood(popup:123)(popup:dialog/faq)"

// I thought this might work, but it creates a very bizarre URL
this.router.createUrlTree([ { outlets: { 'primary': 'dogfood', 'popup': null }} ], { relativeTo: this.activatedRoute  }).toString();
"/store/products(dogfood)(popup:dialog/faq)"   // what is this!!!???

In the end this was the best I could come up with

 import { PRIMARY_OUTLET } from "@angular/router";

 this.router.createUrlTree([ 'dogfood' ], { relativeTo: this.activatedRoute  })
            .root.children[PRIMARY_OUTLET].toString()

 "/store/products/dogfood"

That may look a little odd, but it’s the same technique shown in the UrlTree documentation.