Ionic-framework: Ionic 2 beta 9 Alerts (succeeding alert issue)

Created on 22 Jun 2016  路  14Comments  路  Source: ionic-team/ionic-framework

Short description of the problem:

When updating to ionic 2 beta 9, I encountered an issue regarding alerts (it was working in beta 7)

The scenario is I have a prompt alert (Alert A) where it has an input and two buttons (Cancel, Ok).
On click of Alert A's "Ok", if the input is invalid, it should prompt a simple error alert (Alert B) which shows the error message and a single button (Ok) to dismiss itself, also Alert A should remain/not be dismissed when Alert B is shown. (so that user can rectify the invalid input in Alert A)

when we upgraded to beta 9, when Alert B is shown, any click on the backdrop or the Alert B's Ok button will not work (i.e Alert B cannot be dismissed)

What behavior are you expecting?

Expect that Alert B can be dismissed / Alert B's button handlers are called.

Steps to reproduce:

  1. Present Alert A
  2. Click on button to show Alert B
  3. Alert B button does nothing, click on backdrop also doesn't dismiss Alert B.
let alertA = Alert.create(
  {title:"Hello Alert A", 
   subTitle:"Alert A", 
   buttons:[
      {text:'Cancel'}, 
      {text:'Ok', handler:(data)=>{
               let alertB = Alert.create(
               {title:"Hello Alert B", 
               subTitle:"Alert B", 
               buttons:[{text:'Ok'}]
               });
               this.nav.present(alertB); 
        //return false to not dismiss alert A
        return false;
      }}
   ]
  });
this.nav.present(alertA);

Other information: (e.g. stacktraces, related issues, suggestions how to fix, stackoverflow links, forum links, etc)

Upon checking, it seems the enabled property of Alert B component wasn't set which is preventing it to call the button handlers. Upon tracing the code, enabled property is set in its ionViewEnter which wasn't called... It seems like a bug of navcontroller (?) where Alert B's fireDidEnter is not called as Alert A's fireOtherLifecycles property is false.

Which Ionic Version? 1.x or 2.x
2.0.0-beta-9

Plunker that shows an example of your issue

http://plnkr.co/edit/oSep0drzegYmwJ8nlhJL?p=preview

Run ionic info from terminal/cmd prompt: (paste output below)

Cordova CLI: 6.0.0
Ionic Framework Version: 2.0.0-beta.9
Ionic CLI Version: 2.0.0-beta.24
Ionic App Lib Version: 2.0.0-beta.14
OS: Windows 7 SP1
Node Version: v4.4.2

reply

Most helpful comment

Ahh ok, i think we got it this time. Would you mind trying this on your alerts:

import {AlertController} from "ionic-angular";

constructor(private alertCtrl: AlertController) {};

coolMethod() {
  let coolAlert = this.alertCtrl.create({
    title: "Cool alert",
    message: "I am a cool alert"
  });
  coolAlert.fireOtherLifecycles = true;
  coolAlert.present();
}

All 14 comments

Hello! Thanks for opening an issue with us. I have started debugging this issue and am gonna put my findings here for the rest of the team. This line is getting called which means that for some reason Ionic is trying to push multiple backdrops. Beta.8 does not have this behavior, looks like a regression in beta.9.

In the meantime @Tiuser4567, if you would like a workaround you could use a toast for your error message. This may actually be better ux than showing multiple alerts at a time. Thanks for using Ionic!

im facing the same issue with the new version of alerts.. i have the same use case.. @jgw96's suggestion is actually a good one.. im considering using it.. by the way, can anyone tell me how to find what the latest version of ionic beta is out there and what's its complete changelog?

@awe-sim I would definitely suggest using a toast. We are going to fix this issue with alerts, but in my opinion using a toast here is better ux than using multiple alerts. But, as i said, that is totally my opinion (: Here is a link to our changelog. Also, we always do a post on our blog and a tweet when we do a new release. Finally, if you want to try out the bleeding edge of Ionic 2 (although you may run into issues/undocumented changes) you can run npm install ionic-angular@nightly in your ionic 2 project to get our latest Ionic 2 nightly release. Thanks for using Ionic!

thanks @jgw96 for answering all the questions.. :)

hi guys.. any word on this? i was expecting this to be resolved in beta10 but it isnt there.. in the meantime, is there a workaround that i can use by manually editing the source somewhere?

Hello @awe-sim , I have good news! We have just finished a complete refactor of how "overlay components" like alert our presented onto the navigation stack which should fix this issue. I will update this issue when a nightly is released that has these changes so that you can test it out. Thanks!

Hello @awe-sim we have a nightly out now that has the overlay components refactor. If you would like to try it out you can run npm install ionic-angular@nightly to install the nightly. Here is how to use an alert with the new api.

import {AlertController} from "ionic-angular";

constructor(private alertCtrl: AlertController) {};

coolMethod() {
  let coolAlert = this.alertCtrl.create({
    title: "Cool alert",
    message: "I am a cool alert"
  });
  coolAlert.present();
}

Hi @jgw96 .. Thank you for your response. I tried upgrading to the nightly version and the upgrade went smoothly. I can see that the API has slightly changed now (the addition of AlertsController) but the issue still remains:

let alert = this.alertsController.create({
    title: 'Destroy World',
    message: 'Are you sure?',
    buttons: [{
        text: 'Cancel',
        role: 'cancel',
        handler: () => {
            console.log('CANCEL');
        }
    }, {
        text: 'OK',
        handler: () => {
            console.log('OK');
            let nestedAlert = this.alertsController.create({
                title: 'Destroy World',
                message: 'Now destroying world. Please stand by.',
                buttons: ['OK']
            });
            nestedAlert.present();
            return false;
        }
    }]
});
alert.present();

The first alert renders fine, but when the second alert renders on top of the first one, it cannot be dismissed either by clicking the buttons or the background. In alert-component.js, this section is being hit for the first alert but not the second one:

AlertCmp.prototype.ionViewDidEnter = function () {
    var activeElement = document.activeElement;
    if (document.activeElement) {
        activeElement.blur();
    }
    var focusableEle = this._elementRef.nativeElement.querySelector('input,button');
    if (focusableEle) {
        focusableEle.focus();
    }
    this.enabled = true;
};

Consequently, since this.enabled !== true, the following code does not run.

AlertCmp.prototype.btnClick = function (button, dismissDelay) {
    var _this = this;
    if (!this.enabled) {
        return;
    }
    // keep the time of the most recent button click
    this.lastClick = Date.now();
    var shouldDismiss = true;
    if (button.handler) {
        // a handler has been provided, execute it
        // pass the handler the values from the inputs
        if (button.handler(this.getValues()) === false) {
            // if the return value of the handler is false then do not dismiss
            shouldDismiss = false;
        }
    }
    if (shouldDismiss) {
        setTimeout(function () {
            _this.dismiss(button.role);
        }, dismissDelay || this._config.get('pageTransitionDelay'));
    }
};
AlertCmp.prototype.bdClick = function () {
    if (this.enabled && this.d.enableBackdropDismiss) {
        var cancelBtn = this.d.buttons.find(function (b) { return b.role === 'cancel'; });
        if (cancelBtn) {
            this.btnClick(cancelBtn, 1);
        }
        else {
            this.dismiss('backdrop');
        }
    }
};

My ionic info:

Cordova CLI: 6.1.1
Gulp version:  CLI version 3.9.1
Gulp local:   Local version 3.9.1
Ionic Framework Version: 2.0.0-beta.10-201606302045
Ionic CLI Version: 2.0.0-beta.31
Ionic App Lib Version: 2.0.0-beta.17
ios-deploy version: Not installed
ios-sim version: 5.0.8 
OS: Mac OS X El Capitan
Node Version: v4.4.2
Xcode version: Xcode 7.3.1 Build version 7D1014 

Ahh ok, i think we got it this time. Would you mind trying this on your alerts:

import {AlertController} from "ionic-angular";

constructor(private alertCtrl: AlertController) {};

coolMethod() {
  let coolAlert = this.alertCtrl.create({
    title: "Cool alert",
    message: "I am a cool alert"
  });
  coolAlert.fireOtherLifecycles = true;
  coolAlert.present();
}

Thanks @jgw96 .. This works.. =).. The ionViewDidEnter method is hit successfully for both alerts.. And tapping the buttons or backdrop works as expected.. =)

An observation, though.. When the nested alert is dismissed, the parent alert's ionViewDidEnter is fired for the second time.. I don't see an issue with it, as it appears to set focus to the first field in the alert.. But just letting you know..

Also, I only need to set the fireOtherLifeCycles flag for the nested alert to get it to work properly..

Thanks for your help mate.. I've been blocked at this for a few days now.. Thanks for giving me a way forward.. =)

A question, though.. Is it possible to prevent the parent alert's ionViewDidEnter from triggering when the nested alert is dismissed?

Hello @awe-sim ! Im so glad we got everything working now, thanks for being patient and working with me on this! So the reason the ionViewDidEnter event is firing on the parent alert a second time is because of fireOtherLifecycles being set to true on the nested alert. By default, alerts have fireOtherLifecycles set to false, so whenever they are closed or opened they do not trigger lifecycle events on whatever view is their parent. To get the second alert to be "enabled" correctly we need those lifecycle events to fire though which is why it works now, but it also means that the lifecycle alerts for the first alert are gonna fire when the nested alert is closed. Unfortunately, at this time i cannot think of a way around this as we never really intended to for two alerts to be open at the same time (although it works now). In the future alerts may be changed to be more native like in the way that two alerts will never be able to be open at the same time and instead will be a queue of alerts. An even better solution for your use case than the one we have put together in this issue may be creating a custom component kind of like toast, but that blocks user interaction like you need. Or, something else you could consider would be to change the workflow slightly to something like this:

  1. Open the first alert
  2. There is an error, the second alert is opened and the first alert is closed with its state saved to a service
  3. User fixes error, first alert is reopened pulling its state from that service

I would suggest asking around on our forums and seeing what ideas the awesome community on there could come up with. Since this issue has been fixed i will be closing this issue, but feel free to comment if you have any other questions, as id be glad to answer. Thanks for using Ionic!

how update the alert color with ionic 2 ??

Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

GeorgeAnanthSoosai picture GeorgeAnanthSoosai  路  3Comments

SebastianGiro picture SebastianGiro  路  3Comments

brandyscarney picture brandyscarney  路  3Comments

Macstyg picture Macstyg  路  3Comments

brandyscarney picture brandyscarney  路  3Comments