Angular's Location service has a method onUrlChange
that registers url events that popstate or hashchange don't, and I need that for a part of my project.
/**
* Registers a URL change listener. Use to catch updates performed by the Angular
* framework that are not detectible through "popstate" or "hashchange" events.
*
* @param fn The change handler function, which take a URL and a location history state.
*/
onUrlChange(fn: (url: string, state: unknown) => void) {
this._urlChangeListeners.push(fn);
this.subscribe(v => { this._notifyUrlChangeListeners(v.url, v.state); });
}
Other than usually, there's no subscription returned, so we can't unsubscribe on destroy. The listener is still intact after navigating away from the route that needs to listen to those events.
My ugly hack for the moment is to filter Location
s private _urlChangeListeners
onDestroy
, but that relies on String(fn) !== '(change) => this.urlFileHandler(change)'
and clearly isn't a nice way.
Is there any other possibility to remove that listener from the listeners?
Angular's Location service has a method onUrlChange
that registers url events that popstate or hashchange don't, and I need that for a part of my project.
/**
* Registers a URL change listener. Use to catch updates performed by the Angular
* framework that are not detectible through "popstate" or "hashchange" events.
*
* @param fn The change handler function, which take a URL and a location history state.
*/
onUrlChange(fn: (url: string, state: unknown) => void) {
this._urlChangeListeners.push(fn);
this.subscribe(v => { this._notifyUrlChangeListeners(v.url, v.state); });
}
Other than usually, there's no subscription returned, so we can't unsubscribe on destroy. The listener is still intact after navigating away from the route that needs to listen to those events.
My ugly hack for the moment is to filter Location
s private _urlChangeListeners
onDestroy
, but that relies on String(fn) !== '(change) => this.urlFileHandler(change)'
and clearly isn't a nice way.
Is there any other possibility to remove that listener from the listeners?
Share Improve this question asked Jan 22, 2020 at 19:15 baaobaao 73.4k18 gold badges150 silver badges207 bronze badges4 Answers
Reset to default 5Not really an answer to the question but I decided to subscribe to it once and use an observable. For example:
import { Location } from '@angular/mon';
export class MyService {
public urlChanged = new Subject();
constructor(private location: Location) {
// This is a shared service so the code only gets called once
location.onUrlChange((url, state) => {
this.urlChanged.next({ url, state });
});
}
}
Then subscribe to it in the normal way, for example:
private sub;
ngOnInit() {
this.sub = this.myService.urlChanged.subscribe(e => {
//Do stuff
});
}
ngOnDestroy() {
this.sub.unsubscribe();
}
To properly unsubscribe the callback, the onUrlChange
method returns a VoidFunction
that, on execution, will unregister the callback function.
const unregister = location.onUrlChange((url, state) => { ... });
// To unregister callback
unregister();
https://angular.io/api/mon/Location#onurlchange
You can use
ngOnDestroy() {
this.location.ngOnDestroy();
}
Ps.: Location is injected at your constructor (private location: Location
).
Since I only use one event suscription, I used this when I need to remove it:
(this.location as any)._urlChangeListeners = [];