Given this code:
ngOnInit() {
this.apiService.getBlogPosts().subscribe(blogPosts => {
this.allBlogPosts = blogPosts;
this.changeDetector.detectChanges();
}));
}
I am trying to understand why I am forced to use this.changeDetector.detectChanges();
The circumstances are that if I load my blog route for the first time, my posts load fine, if I route
to another page (either another component
or the same "blog" component
to show the details of a particular post (e.g. 'blog/my-post')) then I route
back to the "blog" component at the root ('blog/'), this time, the template fails to update with the posts. I can see in my Inspect
, Network
tab, that the route to get the posts is still working, console.log
is showing that all seems well through-out, however the template fails to update unless I force change detection. Is this expected behavior? Can it be remedied? This seems strange...
Another thing worth noting is that both first time and the 3 time that I visit the "blog" component
I use:
this.router.navigate([`/${url}`]);
To navigate to it... and this can not be helped...
Edit: the getBlogPosts()
method is in my ApiService
that I inject into my BlogComponent
:
public getBlogPosts() : Observable<BlogPost[]> {
return this.http.get(`${ environment.apiUrl }GetBlogPosts`, { headers: this.headers })
.map((response: Response) => <BlogPost[]>response.json());
}
Angular uses NgZone
to get notified whenever the change detection cycle should be run. NgZone
uses zone.js
under the hood that intercepts all async operations like setTimeout
, new Promise
, XHR
requests etc. So usually it works without any additional efforts from the developer.
However, if you some operation that is not catched by zone.js
you don't get change detection triggered and have to do that manually. But you can use NgZone
to execute some action in the Angular zone meaning Angular will run change detection after the callback has finished executing.
So in your case you can try something like this:
this.routerSubject.subscribe((url: string) => { NgZone.run(() => this.router.navigate([/${url}]); });
where NgZone
can be injected into any Angular component or service:
constructor(zone: NgZone) {}