Reputation: 259
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
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
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
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