28

I want to detect when a page is refreshed using a router in my single-page application (Angular project).

Is there an alternate way?

Khaled Ayed
  • 1,121
  • 3
  • 12
  • 29

5 Answers5

31

In the component.ts file:

import { Subscription } from 'rxjs';

export let browserRefresh = false;

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})

export class AppComponent implements OnDestroy {

  subscription: Subscription;

  constructor(private router: Router) {
    this.subscription = router.events.subscribe((event) => {
        if (event instanceof NavigationStart) {
          browserRefresh = !router.navigated;
        }
    });
  }

In the page you need:

import { browserRefresh } from '../app.component';

....

  ngOnInit() {
    this.browserRefresh = browserRefresh;
    console.log('refreshed?:', browserRefresh);
  }

See a working example at https://stackblitz.com/edit/refreshangular?file=src%2Fapp%2Fpage-a%2Fpage-a.component.ts

Click on page A and Page B. Refresh to see the difference.

Click on page A and Page B. Refresh to see the difference2

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Inês Gomes
  • 4,313
  • 1
  • 24
  • 32
  • 3
    Nice! The StackBlitz made your solution easy to understand. – StackOverflowUser Sep 09 '20 at 08:22
  • Nice, but I'll implement as a service rather than an import from app.component because will cause a performance issue on large applications – jcdsr Feb 24 '21 at 18:17
  • How is this supposed to solve it? router.navigated is alway false. No matter you type the url to new tab or you refresh it. Also in stackblitz console it writes true in both cases. – char m Feb 25 '21 at 14:33
  • @char 5 I edit the question. You need to click on page A or B to see that doesn't refresh and then if you refresh or type url will be refresh= true – Inês Gomes Feb 25 '21 at 20:07
  • thanks! I understand but here typing the url i.e starting new session and refreshing session are the same. at least i would like to know if the existing session is refreshed. this is not solution for that. it can be done in most browsers but i haven't found a way that works in Safari – char m Feb 26 '21 at 17:29
  • @charm I am using Safari.Yes typing the url or refreshing session, are the same. To change page by routing (click button Page B) is not refreshing. I don't understand what you need? – Inês Gomes Feb 26 '21 at 20:56
  • To detect the broser refresh like the title says. This happens when user has a session like myapp:4200/pageX and hits F5 or browser's Refresh button. Then it shoukd get back to myapp:4200/pageX and detect that the existing session was refreshed. My app is quite complex and i need to know. Other browsers provide this info by calling performance.getEntriesByType('navigation'). In Safari the array is empty. – char m Feb 28 '21 at 04:07
23

Try this:

  this.router.events
    .pipe(filter((rs): rs is NavigationEnd => rs instanceof NavigationEnd))
    .subscribe(event => {
      if (
        event.id === 1 &&
        event.url === event.urlAfterRedirects
      ) {
          // Your code here for when the page is refreshd
      }
    })

You will need to import

import { filter } from 'rxjs/operators'
import { Router  } from '@angular/router';
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ghoul Ahmed
  • 4,446
  • 1
  • 14
  • 23
  • I used this code and it worked for me the first two times (i am able to execute some code when user clicks refresh button) but it suddenly stopped working (my mentionned code is not executed anymore) and i did not change anything since. So how is this happening ?. I am using Firefox 71.0 – GB11 Dec 23 '19 at 11:36
  • I assume you are using `import { filter } from 'rxjs/operators'` – DeadlyChambers Jan 14 '21 at 17:32
  • @DeadlyChambers, yes ```import { filter } from 'rxjs/operators';``` – Ghoul Ahmed Jan 14 '21 at 22:04
  • 1
    does this really works? because in my application I am checking on `unload` event so I want to know if using angular routing do the same thing – Kardon63 Apr 09 '21 at 08:48
4

An Angular application is a single-page application, and in the context of a single-page application the full app is loaded once, and data or screens are refreshed as the user uses your application.

A browser refresh is the equivalent of shutting down your application and launching it again. There isn’t any default way to respond to this inside your Angular application.

You might be able to mock something up using onBeforeUnload() to log that the application was reloaded; and then check that log in your application's initialization routine to perform some special action.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
JeffryHouser
  • 39,401
  • 4
  • 38
  • 59
  • 2
    If you're using sessionStorage the session remains and if your app is using this sessionStorage then it's not the same as shutting down and launching, because sessionStorage will persist between reloads. It only gets cleaned either manually or when the window(/tab) closes. –  Feb 06 '20 at 01:32
2

The newest way in Angular 7 and later is that we can now add route navigation properties.

So if /somepage is the page we want to detect and if the browser was refreshed, we set the navigate property prevPage when we go to this page:

this.router.navigate(['/somepage'], { state: { prevPage: this.router.url } });

Then inside somepage:

ngOnInit(): void {
    const previousUrl = history.state.prevPage ?? null;
    if (!this.previousUrl) {
      console.log('page was refreshed!');
    } else {
      console.log('I came here from: ', previousUrl);
    }
}

Note: This works if you want to detect browser refresh from a specific page.

If you need this throughout the site then I would go with a different approach.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
brett
  • 261
  • 1
  • 5
  • 16
1

I want to detect when page is refresh using router

You add a top level resolver to the router. If you have a single top level router, then it will only be resolved once and children will handle page navigation. Each time the resolver is resolved is equal to a page refresh in the browser.

const routes: Routes = [
  {
    path: '',
    component: TopComponent,
    resolve: { loaded: PageLoadedResolver },
    children: [
         ...
    ]
  }
];

There are many other ways of detecting a page load event in Angular.

The constructor of your AppModule.

@NgModule({...})
export class AppModule {
     public constructor() {
          console.log('page loaded');
     }
}

A service injected into the root that is used at least once.

@Injector({provideIn: 'root'})
export class MyService {
     public constructor() {
          console.log('page loaded');
     }
}

There is also the main.ts file which bootstraps the Angular application.

    platformBrowserDynamic().bootstrapModule(AppModule)
        .then(() => console.log('page loaded'))
        .catch(err => console.error(err));

Basically, anywhere there is JavaScript that runs once...

Reactgular
  • 52,335
  • 19
  • 158
  • 208