Reputation: 6326
I have an angular site in which I've inserted some code to make the browser back button behave in the same way as the back UI button. However when I press back on the browser I get the last visited page flashing for a second before the default behavior executes.
Here's a video to show what I mean - at the end I show the what clicking the UI button does which is what I want to emulate: Browser Back Button Demo
And here's the code I'm using in Angular:
@HostListener('window:popstate', ['$event'])
onBrowserBackBtnClose(event: Event) {
// Stop default behavior of the back button
event.stopPropagation();
event.preventDefault();
// If we can go back...
if (this.canGoBack) {
// Load the previous question
this.questionService.previousQuestion().subscribe(res => {
// Activate the question route in place of the previous page
this.router.navigate(['question'], {replaceUrl: true});
});
}
}
My understanding was that event.stopPropagation();
and event.preventDefault();
stopped this flickering behavior? Or is there something else I'm not understanding or missing?
Upvotes: 6
Views: 1777
Reputation: 299
My way to fix this issue: I have some element table and I can open each element detail page by click in row. After browser back navigation in detail page I need to scroll and highlight element row in table. For this i need to navigate by fragment(element id)
// if i have fragment
this.backQuery = window.history.state.query;
this.backFragment = window.history.state.fragment;
history.pushState(null, '');
And i need to listen browser back navigation event
@HostListener('window:popstate', ['$event'])
onPopState(event: any): void {
if (this.backFragment) {
let query = '';
if (this.backQuery) {
Object.keys(this.backQuery).forEach(key => {
query = query + key + '=' + this.backQuery[key] + '&';
});
query = '?' + query.replace(/\&$/g, '');
}
window.location.href = `table-page${query}#${this.backFragment}`;
}
}
Upvotes: 0
Reputation: 26075
You cannot cancel popstate event in the browser, read more about the event on MDN page. That being said, you can update window history (technically a hack) and push current location again so that page will be navigated back to current page using:
window.history.pushState(null, null, window.location.pathname);
Not sure, how you can apply it to your code as I do not have working demo of your app, but it could look something like:
@HostListener('window:popstate', ['$event'])
onBrowserBackBtnClose(event: Event) {
// prevent browser from moving to different page
window.history.pushState(null, null, window.location.pathname);
// If we can go back...
if (this.canGoBack) {
// Load the previous question
this.questionService.previousQuestion().subscribe(res => {
// Activate the question route in place of the previous page
this.router.navigate(['question'], {
replaceUrl: true
}); // you will need some other code to determine and navigate to next page if user chooses to
});
}
}
Upvotes: 0
Reputation: 3593
If I was you I would rather use native Angular approach here. In this particular case you can implement CanDeactivate or CanActivate Route Guards.
In both of this interfaces methods uses asynchronous returns such as:
Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree
Upvotes: 1