Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 6/7 Auxiliary outlet navigating to by route - clears primary outlet and it shouldn't

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.

like image 851
Teresa Burger Avatar asked May 03 '19 04:05

Teresa Burger


1 Answers

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

like image 77
pixelbits Avatar answered Oct 23 '22 05:10

pixelbits