Reputation: 5782
I have two Angular mini-apps on the same page. (Long story.) One is a navigation app, and one is the main app. I'm using the latest Angular router, based on angular/vladivostok.
It appears that the Angular router in one app (e.g., nav) does not respond to URL changes instantiated by the other app (e.g., the main app). So I've created a RouterSynchronizer
1 class that I provide to both apps. It listens to both routers' NavigationEnd
events. When one router (let's call it the "source") has an event, it calls navigateByUrl
on the other router (let's call it the "subscriber").
This works fine for the most part. However, it doesn't call ngOnInit
on the components of the subscriber.
I've created a Plunk to demonstrate this, based on the live example from Angular's official Routing & Navigation guide. Note that when you click the "Crisis Center" and "Heroes" links in the main app, ngOnInit
is not called on the corresponding child components in the nav component. However, when you click those links in the nav component, ngOnInit
is called on those child components, but not on the child components of the main app (which results in the lists of heroes/crisis centers being empty).
Any ideas? Thanks!
1 RouterSynchronizer
class:
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);
});
}
});
}
}
Upvotes: 2
Views: 5774
Reputation: 5782
I figured it out! Apparently, I needed to use a zone. See the new Plunk for implementation.
The problem (I think!) is that my RouterSynchronizer
class was instantiated and provided outside the Angular context. So it wasn't in an Angular zone when it pushed changes to the routers via navigateByUrl
. Once I wrapped the navigateByUrl
call in a zone provided by the app, it worked :)
Upvotes: 3
Reputation: 209
You have to implement OnInit like so:
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;
}
}
Upvotes: -1