37

How I would check internet connection in Angular2 at the time of API hitting, whenever in my app API is hit to server sometimes user is offline (i mean without internet connection) so how would i check the internet connectivity ? is there some special status code for internet connectivity ? or something else ?

PS:- i found navigator.onLine in angularJs but seems not working in angular2.

update

as sudheer suggested in answer below navigator.onLine in working with angular2 but still not working properly why ? working example here

Community
  • 1
  • 1
Pardeep Jain
  • 84,110
  • 37
  • 165
  • 215
  • 5
    I checked this with Windows 10 and Chrome. It always return 'true', if at least one network adapter is connected. So if you have installed a virtual adapter, like the "HostOnly-Network" from VirtualBox, you always get 'true', until you disable this too. :( – Stefan Apr 12 '17 at 18:37

9 Answers9

45

(2018) Code updated for rxjs6

It totally works with angular2. Obviously it's different from angularJS because neither $scope nor $apply exist anymore. RxJS makes this easy, though! Tested on Chrome 53:

template:

<p>{{online$ | async}}</p>

component:

import { Observable, fromEvent, merge, of } from 'rxjs';
import { mapTo } from 'rxjs/operators';

@Component({ /* ... */ })
export class MyComponent {
  online$: Observable<boolean>;

  constructor() {
    this.online$ = merge(
      of(navigator.onLine),
      fromEvent(window, 'online').pipe(mapTo(true)),
      fromEvent(window, 'offline').pipe(mapTo(false))
    );
  }
}

Think about what 'offline' means for your use case!

An unplugged ethernet cable and a 3KB/s EDGE connection likely have the same implications for your app although the latter means you're not technically offline!

From a programmer's point-of-view being connected wirelessly with a very poor signal is actually a lot worse than being truely disconnected because it's a lot harder to detect!

The above code returning a false value means your absolutely offline as in disconnected. It returning true doesn't necessarily indicate that there's a practically usable connection.

j2L4e
  • 6,914
  • 34
  • 40
14

At first, j2L4e's answer didn't work for me (testing in Chrome). I tweaked slightly by surrounding my bool in brackets in the ngIf and this ended up working.

<md-icon class="connected" mdTooltip="No Connection" *ngIf="!(isConnected | async)">signal_wifi_off</md-icon>

import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Subscription } from 'rxjs/Subscription';
import 'rxjs/Rx';

@Component({
  selector: 'toolbar',
  templateUrl: './toolbar.component.html',
  styleUrls: ['./toolbar.component.css']
})
export class ToolbarComponent implements OnInit {
  isConnected: Observable<boolean>;

  constructor() {
    this.isConnected = Observable.merge(
      Observable.of(navigator.onLine),
      Observable.fromEvent(window, 'online').map(() => true),
      Observable.fromEvent(window, 'offline').map(() => false));
  }

  ngOnInit() {

  }
}
Darth_Evil
  • 591
  • 1
  • 7
  • 18
  • 4
    why import 'rxjs/Rx' library. That's huge and bad practice. moreover, Observable and Subscription have already been imported. – Oduwole Oluwasegun Oct 19 '17 at 00:16
  • It is always connected! Is connected flag is always true (on latest chrome version), not sure why the state isn't changing! – Ali Baig Nov 13 '17 at 09:24
11

As i have checked navigator is global object like window. You can use in in angular2 and it worked fine for me.

import {Component} from 'angular2/core';
@Component({
    selector: 'my-app',
    template:`
navigator.onLine
{{onlineFlag}}

`
})
export class AppComponent {
  public onlineFlag =navigator.onLine;
}
Sudheer KB
  • 1,596
  • 14
  • 28
8

Using Angular 6+ and Rxjs 6+, you can do it in the following way:

import { Observable, fromEvent, merge, of } from 'rxjs';
import { mapTo } from 'rxjs/operators';

online$: Observable<boolean>;

constructor() {
  this.online$ = merge(
    of(navigator.onLine),
    fromEvent(window, 'online').pipe(mapTo(true)),
    fromEvent(window, 'offline').pipe(mapTo(false))
  )
}

Here is a demo (toggle network in dev tools)

Michael Doye
  • 8,063
  • 5
  • 40
  • 56
2

Safe Approach to listen to network states

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

1.Browser dependent objects like window 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(mapTo(false));
  const online$ = fromEvent(window, 'online').pipe(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.

abhay tripathi
  • 3,547
  • 4
  • 20
  • 25
2

For Angular 9 - a very simple solution and comfortable using (thanks to this and this solutions):

1) Create new component:

ng g c NoConnection

no-connection.component.ts

import { Component, OnInit } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser'
import { HttpClient }    from '@angular/common/http';

@Component({
  selector: 'app-no-connection',
  templateUrl: './no-connection.component.html',
  styleUrls: ['./no-connection.component.css']
})
export class NoConnectionComponent implements OnInit {

  isConnectionAvailable: boolean = navigator.onLine; 

  constructor(private httpClient: HttpClient) { 
      window.addEventListener('online', () => {
        this.isConnectionAvailable = true
    });

    window.addEventListener('offline', () => {
        this.isConnectionAvailable = false
    });
  }

  ngOnInit(): void {
  }

}

no-connection.component.html (customise page as you want)

<div>

    <p style.color = "{{ isConnectionAvailable  ? 'green' : 'red'}}"> {{ isConnectionAvailable  ? 'Online' : 'Offline'}} </p>  

    <!-- https://stackoverflow.com/questions/13350663/greyed-out-waiting-page-in-javascript#answer-13350908 -->
    <div id="blackout" class="noselect" style.display = "{{isConnectionAvailable ? 'none' : 'block'}}">
        <br><br><br><br><br>
        <p>No Internet connection!</p>
        <br>
    </div>

</div>

no-connection.component.css

#blackout {
    width:100%;
    height:100%; /* make sure you have set parents to a height of 100% too*/
    position: absolute;
    left:0; top:0;
    z-index:10; /*just to make sure its on top*/

    opacity: 0.5; 
    background-color:#333; 
    text-align: center;

    font-size:25px; 
    color: white;
}

.noselect {
  -webkit-touch-callout: none; /* iOS Safari */
    -webkit-user-select: none; /* Safari */
     -khtml-user-select: none; /* Konqueror HTML */
       -moz-user-select: none; /* Old versions of Firefox */
        -ms-user-select: none; /* Internet Explorer/Edge */
            user-select: none; /* Non-prefixed version, currently
                                  supported by Chrome, Opera and Firefox */                               
}

2) Use it anywhere you want - in my case the best place - is a root component:

app.component.html

<div>

    <app-no-connection></app-no-connection>

    <app-main></app-main>

</div> 
chatlanin
  • 5,257
  • 2
  • 16
  • 16
0

Go with this simple Hack.

Working in angular 5 or later

 constructor(){
    setInterval(()=>{
       if(navigator.onLine){
         //here if it is online
       }else{
        //here if it is offline
       }
    }, 100)
 }

write this in constructor of app.component.ts or your app bootstrap No need of any external library ..

0
import { Injectable } from '@angular/core';
import {
    HttpRequest,
    HttpHandler,
    HttpEvent,
    HttpInterceptor
} from '@angular/common/http';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class InternetInterceptor implements HttpInterceptor {
    constructor() { }

    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        // check to see if there's internet
        if (!window.navigator.onLine) {
            // if there is no internet, throw a HttpErrorResponse error
            // since an error is thrown, the function will terminate here
            return Observable.throw(new HttpErrorResponse({ error: 'Internet is required.' }));

        } else {
            // else return the normal request
            return next.handle(request);
        }
    }
}
  • Please always describe what you are doing in your answer. It should be updated or removed. Read [How to answer](https://stackoverflow.com/help/how-to-answer) before you provide more answers ^^ – finnmglas Jul 21 '20 at 08:08
-3

Use this.

Without any external library.

public isOnline: boolean = navigator.onLine;

ngOnInit() { 
    console.log(this.isOnline); 
}
Deepak swain
  • 3,380
  • 1
  • 30
  • 26