5

Lazy loading and using named outlets. I have gotten the named outlet to load as expected but when it does, it is also clearing the primary outlet. I want the primary outlet to keep the component it is displaying and just the named outlet to change to show new component.

Thanks to some help from @pixelbits... here is an example of what is not working https://stackblitz.com/edit/angular-sw6cmc

I don't want the primary outlet to change.

The html

<router-outlet></router-outlet>
<router-outlet name="dialogOutlet"></router-outlet>

The route:

 {    
    path: 'packoutdialog'
    , children:[
      {path:'', outlet:'dialogOutlet', component: PackoutComponent}]

  },

Either of these will fill the dialogOutlet but clear the primary

 this.router.navigate(['inventory', 'packoutedialog'])
this.router.navigate(['packoutdialog',{outlets:{'dialogOutlet':[]}}],{skipLocationChange: true, relativeTo: this.activatedRoute.parent});

This seems like it should work but does not.

this.router.navigate([{outlets:{'dialogOutlet':['inventory','packoutdialog']}}])

the expected result is that the primary router-outlet keeps the view in it and only the named outlet changes. Currently the named outlet is changing as expected but the primary outlet is getting cleared.

Teresa Burger
  • 137
  • 1
  • 3
  • 8

1 Answers1

5

When you have primary outlets and auxiliary outlets together, you need to make sure that both routes fully resolve to a component. In fact, you should consider each route path in isolation.

For example, if you have a component which sets up a router outlet, and a named router outlet:

<router-outlet></router-outlet>
<router-outlet name="dialogOutlet"></router-outlet>

Then you need to make sure that each route can resolve to a component:

{ path: 'inventory', component: InventoryComponent, children: [...] }, 
{ path: 'packoutdialog', component: PackoutComponent, outlet: 'dialogOutlet' }

Notice that the packoutdialog route for the named outlet dialogOutlet needs to be defined at the root level. If you defined the named outlet as a child route, it would never resolve.

To navigate to these routes:

this.router.navigate([{ outlets: { primary: 'inventory', dialogOutlet: 'packoutdialog'} }]);

The primary route will resolve to the InventoryComponent and the named outlet will resolve to the PackoutComponent.

To clear the dialog, you could specify a path for both explicitly:

this.router.navigate([{ outlets: { primary: 'inventory', dialogOutlet: null}]);

Or, if you want to be able show the dialogOutlet regardless of the primary route, you can navigate without explicitly defining a primary route:

this.router.navigate([{ outlets: { dialogOutlet: 'packoutdialog'}]);

Then to clear the dialog:

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

Demo

The above also works for lazy loaded modules.

Demo with Lazy Module 1 Demo with Lazy Module 2

Tony Brasunas
  • 4,012
  • 3
  • 39
  • 51
Michael Kang
  • 52,003
  • 16
  • 103
  • 135
  • that would be great but this - { path: 'packoutdialog', component: PackoutComponent, outlet: 'dialogOutlet' } - doesn't work when you have lazy loading. I found the trick of having the empty child with the outlet here https://github.com/angular/angular/issues/10981#issuecomment-301787482 . Once I do it with the empty child, it does work but I Only want to change the outlet router box and just don't want the primary one to change at all. I don't want to refill it, I just want it to remain with what ever it has. – Teresa Burger May 03 '19 at 13:30
  • you can see in my question that I have tried this.router.navigate([{ outlets: { dialogOutlet: 'packoutdialog'}]); and other itterations of it that I think should work and it doesn't. I believe that is the problem. With my route, I can't figure out how to call it using the outlets syntax. It does go to the outlet using the parent route but then the primary gets cleared. – Teresa Burger May 03 '19 at 13:34
  • This also works with lazy loaded modules. Check the demo link above. – Michael Kang May 04 '19 at 01:21
  • Interesting... I tried to play with it to show what I am trying to do. I was unsuccessful in the short amount of time I have right now. I want the secondary to change without changing the primary and the primary and secondary components are part of the lazy loaded module. I really appreciate all your time. I will return to this to layout the issue - hopefully tomorrow. Thank you so much for taking your time. I really do want to understand this better and get to the bottom of what I am (hopefully) doing wrong. It may be here. I promise to return to it soon. – Teresa Burger May 05 '19 at 14:31
  • I was able to replicate my issue https://stackblitz.com/edit/angular-sw6cmc I took your demo and moved foo, component1 and component2 to the lazy loading module. I proved that if it doesn't have the secondary outlet, it does work and if it has the secondary outlet, it doesn't. Please let me know what I am missing here. – Teresa Burger May 06 '19 at 03:57
  • trying to get what is here stackblitz.com/edit/angular-sw6cmc to work is what lead me to the hack that lead to the question I posted which is the issue with the hack. If I can get stackblitz.com/edit/angular-sw6cmc to work then I am golden. If I can't, I would at least like to understand why it doesn't work. – Teresa Burger May 06 '19 at 04:06
  • 1
    Got your use case to work: https://stackblitz.com/edit/angular-vcqged. Moved 'secondary' named outlet to app-module level, and removed it from the lazy module – Michael Kang May 06 '19 at 04:41
  • You are wonderful!!! Thank you. That is the piece I was missing. If you have a favorite project I can donate to, just let me know. You just saved me from a very ugly work around. – Teresa Burger May 06 '19 at 12:19