Watch for Network Status Changes with Capacitor

One of the key elements of every Progressive Web App (PWA) is that they are offline capable. This means that regardless of whether the user currently has Internet connectivity, they should still be able to use your app with cached data returned. While this post isn’t going to go into the finer details of caching data, I wanted to highlight how you could demonstrate to the user that they are viewing cached data. Further, since some features may not be usable when offline, you may want to alert the user if they try to perform such an action because that data may be lost.

Changing your app’s header color is a great way to make it clear to the user that they are in “offline” mode. So, in this example, when the user doesn’t have Internet connectivity, we will turn the header red. Conversely, when the user does have Internet connectivity, the header will remain the app’s primary color.

We will start by creating a new blank Ionic Angular project, with Capacitor included, navigate into that directory, and serve it so we can begin to see the changes while we code:

$ ionic start network-watcher blank --type=ionic-angular --capacitor
$ cd network-watcher
$ ionic serve

When opening the newly created project, we will have the default blank project setup. We can then generate a service to handle the network watcher logic:

$ ionic g service network

After opening up the new network.service.ts file we can add a plugin listen handler for the Network. As it listens to the “networkStatusChange” message, we can emit the new NetworkStatus via a BehaviorSubject. We can also create a getter method that can be used from our home page to observe these emitted changes. This should look something like the following:

// network.service.ts
...
import { NetworkStatus, PluginListenerHandle, Plugins } from "@capacitor/core";
const { Network } = Plugins;
...
export class NetworkService implements OnDestroy {
  private handler: PluginListenerHandle;
  private status = new BehaviorSubject<NetworkStatus>(null);

  constructor() {
    this.handler = Network.addListener("networkStatusChange", (status) => {
      console.log("Network status changed", status);
      this.sendStatusChangeMsg(status);
    });
  }
  ...
  public getStatusChangeMsg(): Observable<NetworkStatus> {
    return this.status.asObservable();
  }

  private sendStatusChangeMsg(status: NetworkStatus): void {
    this.status.next(status);
  }
}

From the home page we will listen to the changes via a Subscription to the NetworkService‘s getter. When a change is observed, we can set a public variable for the connected status. That connected variable will be referenced in the home.page.html file to update the ion-header‘s color. This will look something like this:

// home.page.ts
...
export class HomePage {
  public connected = true;

  constructor(private networkService: NetworkService) {
    this.setupSubscriptions();
  }

  private setupSubscriptions() {
    this.networkService.getStatusChangeMsg().subscribe((res) => {
      if (res) {
        this.connected = res.connected;
      }
    });
  }
}
<!-- home.page.html -->

<ion-header [translucent]="true">
  <ion-toolbar [color]="connected ? 'primary' : 'danger'">
    <ion-title> Network Watcher </ion-title>
  </ion-toolbar>
</ion-header>

<ion-content [fullscreen]="true">
  ...
</ion-content>

After creating the service to emit the changes, accepting those change’s inside of the page, and updating the color property depending on the connectivity status, you should see this:

You can mimic Internet connectivity changes by using the Network tab in the inspector and toggling Online and Offline.

Outside of changing the header color, one alternative route would be to use Capacitor’s Toast plugin to alert the user of network changes as well. To do this, we would add the Toast plugin to home.page.ts. But first, Ionic’s pwa-elements need to be installed and added to the main.ts file. I would kill the app and re-serve after making this change. Then, after updating the variable holding the connectivity status, we can call a separate function to show a Toast for a short duration. This would look as follows:

$ npm install @ionic/pwa-elements
// main.ts
...
import { defineCustomElements } from "@ionic/pwa-elements/loader";
...
// Call the element loader after the platform has been bootstrapped
defineCustomElements(window);
// home.page.ts
...
import { Plugins } from "@capacitor/core";
const { Toast } = Plugins;
...
export class HomePage {
  ...
  private setupSubscriptions() {
    this.networkService.getStatusChangeMsg().subscribe((res) => {
      if (res) {
        this.connected = res.connected;
      }
      this.showNetworkChgToast();
    });
  }

  private async showNetworkChgToast() {
    await Toast.show({
      text: `Network Connectivity: ${this.connected ? "Online" : "Offline"}`,
      duration: "short",
    });
  }
}

All of that will result in the following results:


That’s all for now! You can find the full code example here.