angularroutesstate

Preserve state in NavigationExtras for subsecondary router outlets


I have a classic main outlet and a secondary named outlet. That secondary outlet has a suboutlet inside.

You can see that structure in Stackblitz here. So, I have:

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

And, inside secondary:

    <router-outlet></router-outlet>

What I want is to pass some info to the suboutlet in secondary. I can pass the info to secondary with NavigationExtras when I do:

this.router.navigate([{ outlets: { secondary: 'about' } }], {
  state: { data: 'My data level 1' },
});

But I need that info in the suboutlet inside 'about', not in 'about'. If I do:

this.router.navigate([{ outlets: { secondary: 'about/subabout' } }], {
  state: { data: 'My data level 1' },
});

I see my subabout page, but I have no state (state remains in 'about', you can see it in console window).

You can see it working by clicking on ABOUT2 menu.

Any ideas to make this work? I know I can do a service to share the info, but if there exists a solution with state, will be cleaner.


Solution

  • For this problem, we can use the decorator SkipSelf.

    This is a dependency injection injector, that skips the instance of the provider on the current component and looks up the DI tree so, it looks at about component's location.

    Also I am using LocationStrategy to get the state, this can be used to solve this problem alone, you should not use it for anything else, since it's having a reference to the parent component location and not on the current location due to the decorator.

    import { LocationStrategy } from '@angular/common';
    import { Component, OnInit, SkipSelf } from '@angular/core';
    import { Router } from '@angular/router';
    
    @Component({
      selector: 'page-subabout',
      templateUrl: './subabout.component.html',
    })
    export class SubaboutComponent implements OnInit {
      constructor(
        private router: Router,
        @SkipSelf() private location: LocationStrategy
      ) {
        console.log('sub about', this.router.getCurrentNavigation()?.extras?.state);
        console.log('sub about location', this.location.getState());
      }
    
      ngOnInit() {}
    }
    

    Stackblitz Demo