Multiple Toasts

Hi Everyone,

How do you deal with multiple toasts?. I sometimes have the occasion where 2 will happen at almost the same time and one will then cover the other up.

My only thoughts were to make a service and queue them, so they pop up one after the other.

What does everyone else do?

Thanks, Ryan

1 Like

You 're on the right track, there.

If you haven’t already, check out the ToastController specification. There it says that when a toast is dismissed via timeout or user input, the onDidDismiss function is called wherein you could notify a custom ToastProvider you have written that pops this specific toast from its queue.

Thanks. Quite easy to implement and works like a charm :slight_smile:

@ryanhow Would you be so kind a paste your custom working solution? :smiley:
Please.

You’ll need to adapt this, but it’s just finds the next item on the queue and shows the toast. A simpler version would be to pop the items from the queue and just check for an empty queue.

    notifications: Array<Notification> = [];
    currentToast: Toast;

    show(notification: Notification) {
        this.notifications.unshift(notification);
        this.runPopupQueue();
    }

    runPopupQueue() {

        if (this.currentToast) return;

        this.notifications.some((notification) => {
            if (notification.popup && !notification.popupDone) {
                this.currentToast = this.toastController.create({message: (notification.important ? ' ! ' : '') + notification.message, duration: 5000, showCloseButton: true, closeButtonText: 'X'});

                this.currentToast.onDidDismiss(() => {
                    this.currentToast = null;
                    this.runPopupQueue();
                });

                this.currentToast.present();
                notification.popupDone = true;
                return true;
            }

            return false;
       });

    }
1 Like

How would you implement this in an angular architecture?

Create a component (QueuedToast), or service? Or something else?

I guess a QueuedToast with embedded ToastQueueService is the cleanest, although I wouldnt mind letting a service do some UI - even though that goes against

Your thoughts?

I just had it in a service and inject the toast controller. Mine is hooked into a larger notifications system.

I just created an array with all msg I need and used that array on the toastController:

public toastMsgs: any = [];

async presentToast(msg) {
    this.toastMsgs.push(msg);
    const toast = await this.toastController.create({
        message: this.toastMsgs.toString().split(",").join("\n"),
        position: 'bottom',
        // showCloseButton: false,
        // closeButtonText: 'Ok',
        duration: 5000
    });
    toast.present();
    toast.onDidDismiss().then(() => {
        this.toastMsgs = [];
    });
}

Result:
Department changed successfully!
Name changed successfully!

1 Like

For Ionic 4 Check this link if helps

// Call this method  
showOnceToast(){
  this.toastController.dismiss().then((obj)=>{
  }).catch(()=>{
  }).finally(()=>{
    this.manageToast();
  });
}

manageToast() {
  this.toastInstance = this.toastController.create({
    message: 'Your settings have been saved.',
    duration: 2000,
    animated: true,
    showCloseButton: true,
    closeButtonText: "OK",
    cssClass: "my-custom-class",
    position: "middle"
  }).then((obj) => {
    obj.present();
  });
}

Here is what works for me:

To avoid the unhandled promise rejection and other errors by Android studio, do the following:

/*the reason for the error is when using toastCtrl.dismiss() it doesn't find any overlay 
toast especially if your code has a toast function to run when intializing the app.
So, to avoid that, we create a toastcontroller with empty parameters then we can 
 dismiss it so the app doesn't give error for not finding anything to dismiss.
By the way, this toastcontroller is not presented, no worries. it's just created.

Define it first inside your class constructor, then you can use separate function
to show and dismiss toasts as in the example below*/
constructor () {
   const toasty = this.toastCtrl.create();
}

async presentToast(msg: string) {

    /* it dismisses the top overlay. so for me it does close any current toast on
    the overlay before showing another one. i tested it with button etc. */
    this.toastCtrl.dismiss();

    const toast = await this.toastCtrl.create({
      message: msg,
      duration: 3000,
      position: 'middle',
      buttons: [{
        icon: 'close-circle',
        role: 'cancel'
      }]
    });

    toast.present();

  }

Good luck!