9

I am trying to write a component that will detect whether the app is online or offline so it can trigger another event. Is there a built-in function that can be leveraged?

Farhan Islam
  • 609
  • 2
  • 7
  • 21

4 Answers4

15
  • To listen to and react to change, you need an event handler. In Angular, Observables are best
  • To be notified of the app coming online or going offline, rely on the online/offline events

    online$ = fromEvent(window, 'online');
    offline$ = fromEvent(window, 'offline');
    

Chain your other events to these:

online$.subscribe(e => this.syncWithServer());

Also see this article about navigator.onLine. Note that browsers don't implement this event uniformly. In some cases, "online" just means that the browser is connected to a local network, not the internet. To get more reliable information, you may need to test by trying to ping a remote server when the event fires.

online$ = fromEvent(window, 'online').pipe(
            switchMap(e => this.pingServer()),
            filter(e => e)
          );

offline$ = fromEvent(window, 'offline').pipe(
            switchMap(e => this.pingServer()),
            filter(e => !e)
          );

Where pingServer will make a remote request and return an observable that emits true when the request is successful, or false otherwise.

BeetleJuice
  • 39,516
  • 19
  • 105
  • 165
  • 1
    to get rid of `Observable.fromEvent is not a function error` ; you should subscribe to `formEvent` itself. .... I use: `fromEvent(window, 'offline').subscribe(() => {this.isOnline = false})` – tabebqena Sep 05 '18 at 13:43
  • 1
    Thanks. This answer was published about a year ago. I've updated it to use RxJS 6 syntax (pipeable operators) – BeetleJuice Sep 10 '18 at 04:30
  • 1
    @BeetleJuice I am using `HttpInterceptor` to check the internet connectivity, but not able to use your code can you explain a bit like where to add those function and observable – Prashant Pimpale Nov 06 '18 at 15:07
6

Safe Approach to listen to network states

Answers given above works well but are not considered safe approach.

1.Browser dependent objects should not be referenced directly, always check for platform.

2.Furthermore functionality like Network Connection must be encapsulated into a service.

Below is the ConnectionService which can be subscribed to listen network states. It follows the rxjs 6 style.

Complete Code

import { Injectable, Inject, PLATFORM_ID } from '@angular/core';
import { Observable, fromEvent, merge, EMPTY } from 'rxjs';
import { isPlatformBrowser } from '@angular/common';
import { mapTo } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class ConnectionService {

  private connectionMonitor: Observable<boolean>;

  constructor(@Inject(PLATFORM_ID) platform) {
if (isPlatformBrowser(platform)) {
  const offline$ = fromEvent(window, 'offline').pipe(startWith(!window.navigator.onLine), mapTo(false));
  const online$ = fromEvent(window, 'online').pipe(startWith(window.navigator.onLine), mapTo(true));
  this.connectionMonitor = merge(
    offline$, online$
  );
} else {
  this.connectionMonitor = EMPTY;
}



 }

  monitor(): Observable<boolean> {
    return this.connectionMonitor;
  }
}

in component, you may listen by subscribing to monitor() or directly into HTML using async pipe.

grim_i_am
  • 3,664
  • 5
  • 19
  • 19
abhay tripathi
  • 3,547
  • 4
  • 20
  • 25
  • 1
    This is the best answer. Relying on online or offline only is not enough (e.g. switching Dev Tools to offline will not change the online$ only the offline$, so the merge is required). Binding the component is as easy as `connection.monitor() | async`. Thanks. – Alexei - check Codidact Oct 31 '20 at 16:53
  • I had to pipe initial values (nothing is emitted on first load): `startWith(!window.navigator.onLine)` and `startWith(window.navigator.onLine)` respectively. – Alexei - check Codidact Oct 31 '20 at 16:59
4
export class HomeComponent implements OnInit {
   public isOnline : boolean = navigator.onLine;
}
1

Another solution with basic javascript functions. Use this below code in app.component.ts file

constructor() {
    window.addEventListener("online", () => {
        alert ("Your browser is working online.");
    });
    window.addEventListener("offline", () => {
        alert ("Your browser is working offline.");
    });
}
Jai Kumaresh
  • 715
  • 1
  • 7
  • 33