2016-06-23 2 views
2

У меня есть две угловые мини-приложения на той же странице. (Длинная история.) Одна из них - навигационное приложение, а одно - основное приложение. Я использую новейший Угловой маршрутизатор, основанный на angular/vladivostok.Angular2 router's navigateByUrl() не вызывает ngOnInit()

Похоже, что угловой маршрутизатор в одном приложении (например, nav) не отвечает на изменения URL, созданные другим приложением (например, основное приложение). Поэтому я создал класс RouterSynchronizer , который я предоставляю обоим приложениям. Он прослушивает события NavigationEnd обоих маршрутизаторов. Когда один маршрутизатор (назовем его «источником») имеет событие, он вызывает navigateByUrl на другом маршрутизаторе (назовем его «подписчиком»).

Это работает отлично по большей части. Однако он не вызывает ngOnInit на компонентах подписчика.

Я создал a Plunk, чтобы продемонстрировать это, основываясь на живом примере официального представителя Angular Routing & Navigation guide. Обратите внимание, что когда вы нажимаете ссылки «Кризисный центр» и «Герои» в главном приложении, ngOnInit не вызывается на соответствующие дочерние компоненты в компоненте nav. Однако при нажатии этих ссылок в навигационном компоненте ngOnInit вызывает эти дочерние компоненты, но не на дочерних компонентах основного приложения (что приводит к тому, что списки героев/кризисных центров пустые).

Любые идеи? Благодаря!

RouterSynchronizer класс:

import { Inject } from '@angular/core'; 
import { NavigationEnd, Router } from '@angular/router'; 

interface ISubscriber { 
    id: string; 
    router: Router; 
} 

export class RouterSynchronizer { 
    private subscribers: ISubscriber[] = []; 

    connect(id: string, router: Router): void { 
    this.subscribers.push({ id, router }); 
    this.startPublishing(id, router); 
    } 

    private startPublishing(source: string, router: Router): void { 
    router.events.subscribe(route => { 
     if (route instanceof NavigationEnd) { 
     this.subscribers.forEach(subscriber => { 
      if (subscriber.id === source || subscriber.router.url === route.urlAfterRedirects) { 
      // Prevent infinite loops. 
      return; 
      } 

      subscriber.router.navigateByUrl(route.urlAfterRedirects); 
     }); 
     } 
    }); 
    } 
} 

ответ

3

Я понял это! По-видимому, мне нужно было использовать зону. См. the new Plunk для реализации.

Проблема (я думаю!) Заключается в том, что мой класс RouterSynchronizer был создан и предоставлен вне углового контекста. Таким образом, он не был в угловой зоне, когда он вносил изменения в маршрутизаторы через navigateByUrl. Как только я завернул вызов navigateByUrl в зону , предоставленную приложением, он работал :)

+2

Если метод, который испускает событие, испускается в другом Угловом экземпляре, тогда зона текущего экземпляр не знает об этом. Вам нужно использовать 'zone.run (() => {}) ', как вы это сделали, чтобы выполнить код в зоне текущего приложения Angular2. –

-1

Вы должны реализовать OnInit так:

import { Component, OnInit } from '@angular/core'; 

@Component({ 
    selector: 'nav-heroes', 
    template: `<span *ngIf="hasRunOnInit">ngOnInit has run in NavCrisisCenterComponent</span>`, 
}) 

export class NavCrisisCenterComponent implements OnInit { 
    private hasRunOnInit: boolean; 

    ngOnInit() { 
    this.hasRunOnInit = true; 
} 
} 
+0

Вы предлагаете добавить «наборы OnInit'? На самом деле это не имеет никакого эффекта времени исполнения. Это всего лишь индикатор компилятора TypeScript того, какие методы он реализует. – jessepinho

+0

Я управлял вашим проектом и реализовал OnInit, это сработало для меня. – Ron

+0

Реализация этой функции позволит вам задействовать крючок жизненного цикла, иначе ваш OnInit - это еще одна функция. Ссылка: https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html#!#spy – Ron

Смежные вопросы