web-dev-qa-db-fra.com

Le routeur Angular2 ajoute un composant au lieu de le remplacer

J'ai une application Angular2 avec une prise de routeur qui affiche différents composants en fonction du lien sur lequel l'utilisateur a cliqué dans un menu latéral.

Le balisage du composant principal contenant le <router-outlet> ressemble à ça

<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 je clique sur le lien Demo, le composant de démonstration est rendu, mais si je clique ensuite sur le lien Accueil, le composant de base est rendu au-dessus du composant de démonstration dans DOM. En cliquant dessus plusieurs fois, vous obtiendrez un DOM comme celui-ci.

<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>

Les itinéraires sont définis comme

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

Comment se fait-il que le <router-outlet> ne remplace pas le composant, mais ajoute une autre "instance" du composant lors du basculement entre les itinéraires?

33
Daniel B

En utilisant la méthode d’élimination, j’ai découvert que le coupable du problème était le module BrowserAnimations de mon app.module.ts. En le retirant de mon imports, le problème a disparu. Je vais regarder dans la création d'un Plunker pour le démontrer.

Mise à jour: Ceci est décrit dans ce numéro de Github .

Mise à jour 2017-12-13: Ceci a maintenant été corrigé avec ce PR, correction (animations): récupère et nettoie correctement le DOM quand CD des échecs se produisent .

53
Daniel B

Cela se produit également lorsque le composant A génère une erreur. Par conséquent, lors de la navigation vers le composant B, le composant A ne peut pas être détruit en raison de l'erreur. C'est un bug avec Angular. Jusqu'à ce qu'ils résolvent, trouvez la cause de l'erreur et corrigez-la. Vérifiez votre console des outils de développement.

20
TetraDev

J'ai eu un problème très similaire, en utilisant également Firebase.

Voir les composants ajoutés à la prise du routeur

Cependant, j'ai constaté que le problème venait d'une erreur dans l'un de mes composants, non liée à mon routage. L'un des composants faisait référence à un "FormsArray", qui n'était ni utilisé ni mal formé. Il y avait des erreurs dans la console devtools, mais je n’avais pas pensé à vérifier, car tout se passait bien.

Je ne sais pas si cela aidera quelqu'un.

6
benjamin ratelade

J'utilisais NgZone dans le composant et mon routerLink rencontrait le même problème, sans erreur dans la console.

Changé le routerLink à un (clic) à l'intérieur et appelé une fonction comme celle-ci:

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

goToPage() {
    this.zone.run(() => this.router.navigate(['/page']));
}
2
António Santos

J'ai eu un problème similaire, et la raison était que j'ai utilisé une directive qui n'est pas déclarée dans le composant A et qu'il n'y avait pas d'erreur dans la compilation ou la console. Ainsi, lorsque vous accédez au composant B, le routeur ajoute le contenu.

Pour déboguer, j'ai commenté tout le balisage HTML dans les deux composants, ne laissant qu'un h1 pour voir si le contenu était ajouté. avec quelques tests, j'ai trouvé la directive et en l'enlevant, le routeur est redevenu normal.

1
Hassan Juniedi

Je ne suis pas sûr que cela corresponde exactement à votre situation. Cependant, j'avais déjà ajouté des composants au DOM lorsque je tentais de charger une route différente. Enfin, j'ai finalement pensé que l'utilisation de Hash était en conflit avec les adresses du composant,

export const AppRouting = RouterModule.forRoot (routes, {seHash: false});

Cela corrigeait tous mes problèmes avec les composants ajoutés indésirables

0
Jaime Gonzalez