24

Here is the issue that I'm encountering with Angular 7 :

I have two outlets : the main app router outlet, and a secondary outlet named 'administration'.

When I want to navigate through any administration link at start, it works fine. But next time, when I try to navigate, angular throws this error message :

Error: Cannot activate an already activated outlet

So, can someone explain me why ? I haven't found any solution on forums...

Here is a stackblitz : https://stackblitz.com/edit/angular-osnnd4

Thank you all everybody :)

Anthony Coucke
  • 251
  • 1
  • 2
  • 5

5 Answers5

30

The problem occurs when lazyloading child routes. You have to manually deactivate the outlet everytime you change a route.

I have modified your AdministrationComponent to workaround as follow. It should be able to work for now, until Angular have a way to solve the problem.

import { Component, OnInit, ViewChild } from '@angular/core';
import { RouterOutlet, Router, ActivationStart } from '@angular/router';

@Component({
  selector: 'app-administration',
  templateUrl: './administration.component.html',
  styleUrls: ['./administration.component.css']
})
export class AdministrationComponent implements OnInit {

  @ViewChild(RouterOutlet) outlet: RouterOutlet;

  constructor(
    private router: Router
  ) { }

  ngOnInit(): void {
    this.router.events.subscribe(e => {
      if (e instanceof ActivationStart && e.snapshot.outlet === "administration")
        this.outlet.deactivate();
    });
  }
}
Lee GuoHong
  • 326
  • 3
  • 2
  • Thank you Lee I will try it at home :) Yeah I read in many thread that Angular has this problem, but I cannot find a way to fix it ^^ – Anthony Coucke Apr 18 '19 at 09:27
  • Thank you @Lee! Does not happen only when you're using lazy loading - also happens when you're using auxiliary named Routers. Just apply the fix, that worked perfectly, after a few days of banging on the wall and try out a million ways of doing the routing switch differently - none have worked, except for this fix. – Pedro Ferreira Jan 06 '20 at 10:59
  • I had this issue when trying to use named (aux) router outlets and found another workaround: https://github.com/angular/angular/issues/20694#issuecomment-595707956 – Andreas Mar 06 '20 at 10:43
  • Just don't use named outlets on both child router outlets. https://github.com/angular/angular/issues/20694#issuecomment-364446781 – Wlada Apr 07 '20 at 11:37
26

This might be silly, but for anyone looking for a solution to this: Make sure that in there's no undefined variable in any of the inner or children outlets.

I fixed this in my project and everything is back to normal.

B. León
  • 529
  • 7
  • 12
5

My problem: Basically my named outlet wasnt deactivating, in my case I would use it for a bunch of different modals, and while manually deactivating my modal outlet would work, it didnt work when loading a different path and the same component into the outlet so I could not recycle my componet, in my case the modal component.

So as pointed by @Andreas in here (https://github.com/angular/angular/issues/20694#issuecomment-595707956). I didn't have any asigned components for an empty path, so I am guessing it couldnt deactivate the outlet somehow because of that, so I just asigned an emptyComponent for path: "".

The first way: to fix this I will be using an empty component for "" or non truthy routes

app-router-module.ts
...
 {
    outlet: "modal",
    path: "", 
    component: EmptyComponent, 
  },
...

Another way: If you want, you can do this instead when closing a view

model.component.ts

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

either way the router deactivates, better yet I think you should use the second example as it deactivates and destroys the view. in my case I had a json with non truthy routes so I just had to map those to null values.

1

Check thoroughly if you have imported a lazy-loaded module in its parent module or some other module irrespective of the routing. If so, remove its import from there. That was it in my case.

0

My problem was that I have a login guard which performs a redirect via this.router.navigate, and the guard was returning true after redirects.

When I changed the code to return false in the case of a redirect, the issue has been gone.

satanTime
  • 12,631
  • 1
  • 25
  • 73