Internet Connection Monitoring Service
Detects whether browser has an active internet connection or not in Angular application.
This library is a fork of https://github.com/ultrasonicsoft/ng-connection-service by Balram Chavan.
Install
npm i ngx-connection-service --save
Server-Side Rendering (SSR)
No extra dependencies are required for Angular Universal / SSR. On the server, the service uses a Window stub with navigator.onLine = true and logs a console warning. Online/offline DOM events are only active in the browser after hydration.
Angular Version Compatibility
Please use following table to determine suitable library version for your Angular project.
| ngx-connection-service version | Angular version |
|---|---|
| 7.0.x | 7.2.16 |
| 8.0.x | 8.2.14 |
| 9.0.x | 9.1.13 |
| 10.0.x | 10.2.5 |
| 11.0.x | 11.2.14 |
| 12.0.x | 12.2.17 |
| 13.0.x | 13.4.0 |
| 14.0.x | 14.3.0 |
| 15.0.x | 15.2.9 |
| 16.0.x | 16.1.8 |
| 17.0.x | 17.1.0 |
| 18.0.x | 18.1.2 |
| 19.0.x | 19.2.25 |
| 20.0.x | 20.3.27 |
| 21.0.x | 21.2.20 |
| 22.0.x | 22.1.2 |
Usage
- Register
provideConnectionService()in your application's providers (standalone /ApplicationConfig).
import {ApplicationConfig} from '@angular/core';
import {provideConnectionService} from 'ngx-connection-service';
export const appConfig: ApplicationConfig = {
providers: [
provideConnectionService(),
],
};
import {bootstrapApplication} from '@angular/platform-browser';
import {AppComponent} from './app/app.component';
import {appConfig} from './app/app.config';
bootstrapApplication(AppComponent, appConfig)
.catch(err => console.error(err));
Legacy
NgModulesetup:ConnectionServiceModuleis still available and works, but is deprecated. PreferprovideConnectionService()above.import {NgModule} from '@angular/core'; import {ConnectionServiceModule} from 'ngx-connection-service'; @NgModule({ imports: [ConnectionServiceModule], }) export class AppModule { }
- Inject
ConnectionServiceusinginject()(or the constructor) in your component. - Read the reactive
stateSignal, or subscribe tomonitor()for push notifications whenever the connection status changes. Both APIs are kept in sync (dual API).
import { Component, inject } from '@angular/core';
import { ConnectionService } from 'ngx-connection-service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
private readonly connectionService = inject(ConnectionService);
// Signal API (recommended for modern, signal-based Angular apps)
readonly currentState = this.connectionService.state;
constructor() {
// Observable API (still fully supported)
this.connectionService.monitor().subscribe(currentState => {
console.log(currentState);
});
}
}
In the template you can then read the Signal directly:
@if (currentState().hasNetworkConnection && currentState().hasInternetAccess) {
<span>ONLINE</span>
} @else {
<span>OFFLINE</span>
}
Configuration
You can configure the service using ConnectionServiceOptions configuration variable.
Following options are available;
/**
* Instance of this interface could be used to configure "ConnectionService".
*/
export interface ConnectionServiceOptions {
/**
* Controls the Internet connectivity heartbeat system. Default value is 'true'.
*/
enableHeartbeat?: boolean;
/**
* Url used for checking Internet connectivity, heartbeat system periodically makes "HEAD" requests to this URL to determine Internet
* connection status. Default value is "//api.ipify.org/".
*/
heartbeatUrl?: string;
/**
* Callback function to used for executing heartbeat requests. Defaults to HttpClient.request(...) function.
*/
heartbeatExecutor?: (options?: ConnectionServiceOptions) => Observable<any>;
/**
* Interval used to check Internet connectivity specified in milliseconds. Default value is "30000".
*/
heartbeatInterval?: number;
/**
* Interval used to retry Internet connectivity checks when an error is detected (when no Internet connection). Default value is "1000".
*/
heartbeatRetryInterval?: number;
/**
* HTTP method used for requesting heartbeat Url. Default is 'get'.
*/
requestMethod?: 'get' | 'post' | 'head' | 'options';
}
You should provide ConnectionServiceOptions via provideConnectionService(options) as follows;
import {ApplicationConfig} from '@angular/core';
import {ConnectionServiceOptions, provideConnectionService} from 'ngx-connection-service';
export const appConfig: ApplicationConfig = {
providers: [
provideConnectionService({
enableHeartbeat: false,
heartbeatUrl: '/assets/ping.json',
requestMethod: 'get',
heartbeatInterval: 3000
} satisfies ConnectionServiceOptions),
],
};
Custom HeartBeat handling function
You could use a callback function for handling heartBeat requests by defining heartbeatExecutor property in ConnectionServiceOptions;
import { Component, inject } from '@angular/core';
import { ConnectionService } from 'ngx-connection-service';
import {Observable} from 'rxjs';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
private readonly connectionService = inject(ConnectionService);
readonly currentState = this.connectionService.state;
constructor() {
this.connectionService.updateOptions({
heartbeatExecutor: options => new Observable<any>(subscriber => {
if (Math.random() > .5) {
subscriber.next();
subscriber.complete();
} else {
throw new Error('Connection error');
}
})
});
}
}
Testing your own code that uses ConnectionService
ConnectionService uses RxJS timer()/debounceTime() internally (heartbeat polling, retry delay, and state
debouncing). If you write unit tests that need to wait for these internal delays, you don't need zone.js's
fakeAsync/tick. Instead, provide ConnectionServiceSchedulerToken with an RxJS TestScheduler
(from rxjs/testing) and advance its virtual clock synchronously:
import {TestBed} from '@angular/core/testing';
import {TestScheduler} from 'rxjs/testing';
import {ConnectionService, ConnectionServiceSchedulerToken} from 'ngx-connection-service';
const scheduler = new TestScheduler(() => {});
TestBed.configureTestingModule({
providers: [
ConnectionService,
{provide: ConnectionServiceSchedulerToken, useValue: scheduler},
// ...your other providers (e.g. provideHttpClient, provideHttpClientTesting)
],
});
const service = TestBed.inject(ConnectionService);
// Advance virtual time by 300ms synchronously instead of really waiting:
scheduler.maxFrames = scheduler.frame + 300;
scheduler.flush();
This keeps tests instantaneous and fully zoneless. ConnectionServiceSchedulerToken is optional — when not
provided, the service defaults to RxJS's regular asyncScheduler (real timers), which is what you want in production.
Changes
- Zoneless: the demo application and library tests no longer depend on
zone.js. The app usesprovideZonelessChangeDetection(); tests use RxJSTestSchedulervirtual time instead offakeAsync/tick. - Standalone-first API:
provideConnectionService()replacesConnectionServiceModuleforApplicationConfig/bootstrapApplicationsetups.ConnectionServiceModuleis kept for backward compatibility but is deprecated. ConnectionServicenow exposes a reactivestateSignal in addition to the existingmonitor()Observable API (dual API, non-breaking).- Demo application converted to standalone components using the new
@ifcontrol-flow syntax andinject(). - This version use https://api.ipify.org/ to determine Internet connection status
- Removed dependency to "ssr-window" package
Security / Dependency Status
Upgrade Matrix (current tree)
| Package group | Previous range | Current range | Decision |
|---|---|---|---|
Angular runtime (@angular/*) |
^21.2.20 |
^22.1.2 |
Upgraded to latest 22.x runtime patches. |
Angular build chain (@angular-devkit/build-angular, @angular/cli, @angular/compiler-cli, @angular/language-service, ng-packagr) |
21.x |
22.x |
Upgraded to latest Angular 22 tooling patches. |
Lint stack (angular-eslint, eslint, @eslint/js, @typescript-eslint/*, typescript-eslint) |
Angular-eslint 21.4.0 |
Angular-eslint 22.1.0 + ESLint 10.x companions |
Upgraded to latest Angular 22-compatible lint toolchain. |
Type defs (@types/node, @types/jasmine) |
previous majors | Latest Node/Jasmine types compatible with current toolchain | Retained at latest compatible versions. |
Test UI reporter (karma-jasmine-html-reporter, jasmine-core) |
2.1.0 / 5.1.x |
2.2.0 / 6.3.x |
Upgraded to latest compatible versions. |
TypeScript toolchain (typescript) |
~5.9.3 |
~6.0.3 |
Upgraded to satisfy Angular 22 peer requirements. |
Overrides (less, uuid, webpack-dev-server) |
Fixed versions in overrides |
removed | Removed; now resolved by upstream transitive graph. |
E2E stack (protractor, jasmine-spec-reporter, ts-node) |
present | removed | Fully removed from current tree. |
Exceptions (latest-version policy with Angular 22 compatibility)
zone.jshas been removed entirely. The application and library now run zoneless viaprovideZonelessChangeDetection();zone.jsis only an optional peer of@angular/coreand is not installed.- Angular runtime/build packages are intentionally pinned to latest
22.x(not23+) to maintain declared Angular 22 compatibility for this release line. @angular/cli22 requires Node.js^22.22.3 || ^24.15.0 || >=26.0.0; run with a matching Node patch version before executing Angular CLI commands.- If a dependency cannot move to its global latest version without breaking Angular 22 peer constraints, it is pinned to the highest Angular 22-compatible release.
License
MIT License Argela Inc. & Balram Chavan (orginal work)