Mohammed Azhar
Mohammed Azhar

Reputation: 259

Dismiss old alert and present latest alert - Ionic3

I am using the alerts of Ionic 3 and I am facing an issue of alerts stacking up. I am using the network plugin to check if the user is connected to a network(WiFi/2G/3G etc.) or not and the idea is to trigger an alert every time the user goes offline or comes online.

this.connectSubscription = this.network.onConnect().subscribe(() => {
  console.log('network connected!');
  let connectedToInternet = this.alertController.create({
    subTitle: 'Connected to Internet',
    buttons: ['OK']
  });
  connectedToInternet.present();
});

this.disconnectSubscription = this.network.onDisconnect().subscribe(() => {
  let noInternetAlert = this.alertController.create({
    subTitle: 'No Internet Connection. Please enable Wifi or Mobile data to continue.',
    buttons: ['OK']
  });
  noInternetAlert.present();
});

Current behaviour: If the user disconnects and reconnects multiple times, for every instance of change in the network, an alert is presented and the alerts stack up on the view until the user manually dismisses the alerts.

Required behaviour: If the user disconnects and reconnects multiple times, for every instance of change in network, an alert should be presented while the older alert automatically gets dismissed so that at any given point in time, the user is not presented with more than one instance of any alert on the view.

Upvotes: 1

Views: 3709

Answers (3)

Mohammed Azhar
Mohammed Azhar

Reputation: 259

The answer marked correct solves the problem asked in the question but alternatively, there's a more elaborate solution that would cover multiple cases of alerts stacking up, which I have successfully implemented. I created a wrapper for AlertController using a provider which would maintain the status of every alert and subsequently dismiss the older alert and present the new alert. The code below is for the provider which is basically the wrapper class I am using for all the alerts that I create in the app:

import {AlertController} from 'ionic-angular';
@Injectable()
export class AlertserviceProvider {
  alerts: any[] = [];

  constructor(public alertController: AlertController) {
  }

  newAlert(title, subTitle){
    let alert = this.alertController.create({
      title:title,
      subTitle:subTitle
    });
    this.alerts.push(alert);
    return alert;
  }

  dismissAlert(){
    if(this.alerts.length){
      this.alerts.forEach(element => {
        element.dismiss();
      });
    }
    this.alerts = [];
  }

}

This can be consumed within the page using the following code:

import { AlertserviceProvider } from '../../providers/alertservice/alertservice';
...
...
...

constructor(..,public alertHandler: AlertserviceProvider,..) {
...
}
testMethod(){
    //First we dismiss the previous alerts if any
    this.alertHandler.dismissAlert();
    //Creating the new alert
    var testAlert = this.alertHandler.newAlert('Title','SubTitle');
    //Adding buttons to the new alert
    testAlert.addButton({
        text: 'OK',
        role: 'OK',
        handler: () => {
          //Handler actions go here - include the Handler only if required
        }
      });
    testAlert.present();
}

Do NOT forget to import your provider and create a variable for it in the constructor parameters.

If you would like to add multiple buttons, the CSS may get messed up. Please take a look at this answer for that problem: https://stackoverflow.com/a/39188966/4520756

Please note that for this solution to work, all your alerts need to be created using this wrapper only. It will not support the alerts created using the default AlertController provided by Ionic. Hope this helps anyone looking to avoid stacking of alerts!

For an alternative and simpler solution covering lesser cases, check out this answer: https://stackoverflow.com/a/39940803/4520756

Credits: https://stackoverflow.com/a/43318081/4520756

Upvotes: 4

Mohan Gopi
Mohan Gopi

Reputation: 7724

isAvailable: Boolean; //boolean variable helps to find which alert we should dissmiss   
connectedToInternet; //made global to get access 
noInternetAlert; // made global to get access


 this.connectSubscription = this.network.onConnect().subscribe(() => {
      console.log('network connected!');

      if(!this.isAvailable){ //checking if it is false then dismiss() the no internet alert
        this.noInternetAlert.dismiss();
      }
       this.isAvailable =true;

      this.connectedToInternet = this.alertController.create({
        subTitle: 'Connected to Internet',
        buttons: ['OK']
      });
      this.connectedToInternet.present();
    });

    this.disconnectSubscription = this.network.onDisconnect().subscribe(() => {

     if(this.isAvailable){// if it is true then dismiss the connected to internet alert
        this.connectedToInternet.dismiss();
      }
      this.isAvailable = false;
      this.noInternetAlert = this.alertController.create({
        subTitle: 'No Internet Connection. Please enable Wifi or Mobile data to continue.',
        buttons: ['OK']
      });
      this.noInternetAlert.present();
    });

Upvotes: 5

Sampath
Sampath

Reputation: 65860

I have done that as shown below.The code is self-explanatory.If you need any explanation please let me know.

I have created a povider as shown below.

network-state.ts

import { Injectable } from '@angular/core';
import { Network } from '@ionic-native/network';
import { ToastController } from "ionic-angular";
import { Subscription } from "rxjs/Subscription";

@Injectable()
export class NetworkStateProvider {

  public isInternetAvailable = true; private connectSubscription$: Subscription = null;

  constructor(private network: Network, private toastCtrl: ToastController) {
  }

  //Watch for internet connection
  public WatchConnection() {
    if (this.connectSubscription$) this.connectSubscription$.unsubscribe();
    this.connectSubscription$ = this.network.onDisconnect().subscribe(() => {
      this.isInternetAvailable = false;
      this.showToast('Internet connection unavailable');
      console.log(this.network.type, this.isInternetAvailable, 'No internet!');
      if (this.connectSubscription$) this.connectSubscription$.unsubscribe();
      this.connectSubscription$ = this.network.onConnect().subscribe(() => {
        console.log('Network connected!');
        setTimeout(() => {
          if (this.network.type === 'wifi' || this.network.type === '4g' || this.network.type === '3g' || this.network.type === '2g' || this.network.type === 'cellular' || this.network.type === 'none') {
            this.isInternetAvailable = true;
            this.showToast('Internet connection available');
            this.WatchConnection();
            console.log(this.network.type, this.isInternetAvailable, 'we got a connection!');
          }
        }, 3000);
      });
    });
  }

  //show Toast
  showToast(message, timeout = 3000) {
    let toast = this.toastCtrl.create({
      message: message,
      duration: timeout,
      position: 'bottom',
    });
    toast.present()
  }

  //check Internet Availability
  checkInternetAvailability(): boolean {
    if (!this.isInternetAvailable) {
      this.showToast('Internet connection unavailable');
       return false;
    } else if (!this.isInternetAvailable) {
      this.showToast('Internet connection unavailable');
      return false;
    } else {
      return true;
    }
  }
}

I have used that provider here:

app.component.ts

constructor(private network: NetworkStateProvider,public platform: Platform){
 platform.ready().then(() => {
       this.network.WatchConnection();
    });
}

Upvotes: 1

Related Questions