Reputation: 468
So my Angular app has a search bar, and if you enter something in this search bar, it does its search and comes to a results page. All good there.
Now if your search doesn't return any results, the results page loads and tells you "searchterm" has returned no results. At this point, the URL is localhost:4200/searchResults;query=searchterm
. Again - all is as expected.
Now, if you go to the search bar, and enter a different search term, nothing happens...
Well, that's not correct... the URL now says localhost:4200/searchResults;query=NEWsearchterm
, but because we are on the 'same' app page, ngOnInit doesn't refire (thus actually searching for the term) NOR does ngOnChanges fire (thus actually searching for the term)...
The routing module seem to do what it was supposed to because our URL did change to reference the new search term, but something isn't happening that should, and I don't know what?
Is this something wrong I'm missing in the routing module (although I wouldn't think so, because the URL did change), or something I'm missing in the Component class on the app page???
Upvotes: 3
Views: 3007
Reputation: 1204
Try to subscribe route changes
class MyClass {
constructor(private router: Router) {
router.events.subscribe((val) => {
if(val instanceof NavigationEnd){
console.log("refreshing");
}
});
}
}
Upvotes: 3
Reputation: 10303
The angular way of telling the router to do this is to use onSameUrlNavigation as of angular 5.1... but I think there are still some troubles with implementing this.
So I had to solve this issue in a different way(Stackblitz), by subscribing
to route events
and actually calling a custom reInit method
.
The trick is to add all subscriptions to the same object and then unsubscribe ONLY when ngOnDestroy
is called by angular, and doing the rest of your template vars change from the custom destroy method
... If you do not have any subscription and do not implement ngOnInit lifcycle ehook, then @Yazan Mehrez's answer should do, but if you do have subscriptions or use the hook, then you need an implementation like the one bellow to prevent memory leaks:
public subscribers: any = {};
constructor(private router: Router) {
/**
* This is important: Since this screen can be accessed from two menu options or has query string parameter changes
* we need to tell angular to reload the component when this happens.
* It is important to filter the router events since router will emit many events,
* therefore calling reInitComponent many times wich we do not want.
*/
this.subscribers._router_subscription = this.router.events.filter(evt => evt instanceof NavigationEnd).subscribe((value) => {
this.reInitComponent();
});
}
reInitComponent() {
this.customOnDestroy();
this.customOnInit();
}
customOnInit() {
// add your subscriptions to subscribers.WHATEVERSUB here
// put your ngOnInit code here, and remove implementation and import
}
customOnDestroy() {
// here goes all logic to re initialize || modify the component vars
}
/**
* onDestroy will be called when router changes component, but not when changin parameters ;)
* it is importatn to unsubscribe here
*/
ngOnDestroy() {
for (let subscriberKey in this.subscribers) {
let subscriber = this.subscribers[subscriberKey];
if (subscriber instanceof Subscription) {
subscriber.unsubscribe();
}
}
}
Note that if you implement lifecylce hook ngOnInit, you should remove it and implement a custom method like in the example.
I added the unsubscription
method because of this angular bug. Angular should actually automatically unsubscribe from router.events when destroying the component, but since this is not the case, if you do not unsubscribe manually you will end up calling http requests(for example) as many times as you entered the component.
Upvotes: 4