Angular2 router añade componente en lugar de reemplazarlo


Tengo una aplicación Angular2 con una toma de router que muestra diferentes componentes dependiendo de qué enlace se haga clic en un menú lateral.

El marcado para el componente principal que contiene el <router-outlet> se ve así

<div *ngIf="authenticated == false">
  <app-login></app-login>
</div>
<div *ngIf="authenticated">
  <div class="page home-page">
    <header class="header">
      <app-navbar></app-navbar>
    </header>
    <div class="page-content d-flex align-items-stretch">
      <div class="sidebar-container">
        <app-sidebar-menu></app-sidebar-menu>
      </div>
      <div class="content-inner">
      <app-page-header></app-page-header>
        <div id="sub-content">
          <router-outlet></router-outlet>
        </div>
        <app-footer></app-footer>
      </div>
    </div>
  </div>
</div>

Si hago clic en el enlace Demo, el componente demo se renderiza, pero si luego hago clic en el enlace Home, el componente home se renderiza encima del componente demo en DOM. Al hacer clic en ellos un par de veces resultará con un DOM como esto

<div _ngcontent-c0="" id="sub-content">
    <router-outlet _ngcontent-c0=""></router-outlet>
  <app-home _nghost-c6="">...</app-home>
  <app-demo _nghost-c7="">...</app-demo>
  <app-home _nghost-c6="">...</app-home> <!-- Why so many here? Should be just either one <app-home> or <app-demo>  -->
  <app-demo _nghost-c7="">...</app-demo>
  <app-home _nghost-c6="">...</app-home>
  <app-demo _nghost-c7="">...</app-demo>
  <app-footer _ngcontent-c0="" _nghost-c5="">...</app-footer>
</div>

Las rutas se definen como

export const router: Routes = [
    { path: 'demo', component: DemoComponent, canActivate: [AuthGuard] },
    { path: 'home', component: HomeComponent, canActivate: [AuthGuard] }
]

¿Cómo es que el <router-outlet> no reemplaza el componente, sino que agrega otra "instancia" del componente al cambiar entre las rutas?

Author: Daniel B, 2017-08-10

6 answers

Usando el método de eliminación, descubrí que el culpable del problema era el módulo BrowserAnimations en mi app.module.ts. Al quitarlo de mi imports que el problema se fue. Buscaré crear un Desatascador para demostrarlo.

Actualización: Esto se describe en este problema de Github.

Actualización 2017-12-13: Esto ahora se ha solucionado con este PR, fix(animaciones): recuperar y limpiar correctamente DOM cuando se producen fallos de CD.

 44
Author: Daniel B,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-13 07:49:59

Esto sucede también cuando el componente A está lanzando un error, por lo que al navegar al Componente B, el Componente A no se pudo destruir debido al error. Este es un error con Angular. Hasta que arreglen, encuentra la causa del error que se está lanzando y arréglalo. Comprueba la consola de dev tools.

 17
Author: TetraDev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-18 17:50:38

Tuve un problema muy similar, también usando Firebase.

Ver los componentes que se anexan a la salida del router

Sin embargo, descubrí que el problema provenía de un error dentro de uno de mis componentes, no relacionado con mi enrutamiento. Uno de los componentes tenía una referencia a un "FormsArray", que no se utilizó y malformado. Arrojó errores en la consola de devtools, pero no pensé en comprobarlo allí, ya que todo estaba compilando bien.

No estoy seguro de si eso ayudará nadie.

 6
Author: benjamin ratelade,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-18 01:14:51

Estaba usando NgZone dentro del componente y mi routerLink estaba teniendo el mismo problema, sin ningún error dentro de la consola.

Cambió el routerLink a un (click) inside y llamó a una función como esta:

constructor(
    (...)
    private zone: NgZone,
    (...)
  ) { }

goToPage() {
    this.zone.run(() => this.router.navigate(['/page']));
}
 1
Author: António Santos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-27 11:45:52

Tuve un problema similar , y la razón fue que usé una directiva que no está declarada en el componente A y no hubo error en compile o console. así que cuando navegue al componente B, el enrutador agregaba el contenido.

Para depurar comenté todo el marcado html en ambos componentes dejando solo un h1 para ver si el contenido estaba anexando. con algunas pruebas encontré la directiva y al eliminarla, el enrutador volvió a la normalidad nuevamente.

 1
Author: Hassan Juniedi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-04 14:50:07

No estoy seguro de si esto coincide exactamente con su situación, sin embargo, he tenido componentes anteriores anexar al DOM al intentar cargar una ruta diferente, y finalmente me di cuenta de que el uso de Hash estaba en conflicto con las direcciones del componente,

Export const AppRouting = RouterModule.forRoot (routes, {useHash: false });

Esto solucionó todos mis problemas con componentes adjuntos no deseados

 0
Author: Jaime Gonzalez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-30 15:43:17