0
votes

Baiscally I have a component which needs to be displayed conditionally upon the activation/deactivation of a named router-outlet. All right on the activation side, but it doesn't work when the url changes back (i.e. someone presses the browser's back arrow): the router-outlet content still being displayed. I think the main problem is that router-outlet being part of a lazy loaded module. I've checked this previous answer for Angular 7, but it has no effects on my project (Angular 9).

Here's my routing module routes

const routes: Routes = [
  { path: '',  component: StudentsComponent },
  { path: ':id/macro',
      component: StudentDetailComponent,
      runGuardsAndResolvers: 'always',
      resolve: { 
        item: StudentDetailResolverService,
        macroAssignments: MacroAssignmentsResolverService
      },
      children: [
        {
          path: ':id/lto',      // ***** PROBLEMS HERE ************************************
          loadChildren: () => import('../lto/lto.module').then(m => m.LTOModule),
          runGuardsAndResolvers: 'always',
        }
      ]
  }
];

And that's the template where's the router-outlet directive

<app-item-detail>
    ...
    <div *ngIf="!outlet.isActivated" list >
        <app-student-detail-macro-list [student]="this.item" [macroAssignments]="this.macroAssignments" ></app-student-detail-macro-list>
    </div>

</app-item-detail>

<router-outlet #outlet="outlet" name='lto-list' (deactivate)='checkOutlet($event)' (activate)='checkOutlet($event)' ></router-outlet>

NOTE: checkOutlet($event) is simply a test to print something on the console when the router-outlet builtin event emitter fires something. This lead me to discover an event is correctly fired when the router-outlet activates, but nothing happens when the the url changes back (so, the router-outlet should deactivates).

Finally, the routing module of the lazy loaded module LTOModule

const routes: Routes = [
  { path: '' , component: LtoListComponent, outlet: 'lto-list' },
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class LTORoutingModule { }

Don't know if it could be useful, but here's also the portion of template where my router-outlet is being activated

<li *ngFor="let macroAssignment of this.macroAssignments" >
    <a [routerLink]="[macroAssignment.macro, 'lto']" >
        <span >{{ macroAssignment.macro_name }}</span>
    </a>
</li>

**************** EDIT *****************

I've noticed that when I press the forth arrow instead, I get the following error: ERROR Error: Uncaught (in promise): Error: Cannot activate an already activated outlet

2

2 Answers

0
votes

I guess that is nothing to do with lazy loaded. You just have to reset the conditions by implementing ngOnDestroy() of the component which gets rendered on clicking the back button.

0
votes

I've found this (ugly, IMHO) workaround. In the component which contains the router-outlet directive, I subscribe to the router event to track changes in the url when the router-outlet is first activated. Then, when the url changes back to the one matching the parent component path, I deactivate the router-outlet.

onActiveOutlet(component: Component) {
    let previousUrl = this.router.url;
        this.router.events.subscribe(
          event => {
            if (event instanceof NavigationEnd) {
              if (previousUrl != this.router.url && previousUrl.includes(this.router.url)) {
                this.outlet.deactivate();
              }
            }
        }
    )
}

And in the parent component template, just catch the event emitted by the outlet when it's activating

<router-outlet #outlet="outlet" name='lto-list' (activate)='onActiveOutlet($event)' ></router-outlet>