ionic-framework: bug: Ionic5.01, Android 6~8, modalController works strange when two modals open togather.

I test it in emulator, android 6,7,8, all of them reproduce the following issues. These issues doesn’t exist in ionic 4.4.

Steps:

  1. create modal A, present it.
let modal = await this.modalCtl.create({
component: modalAClass
....
});
modal.present();
  1. in modal A, create modal B.
let modal = await this.modalCtl.create({
component: modalBClass
....
});
modal.present();
  1. in modal B, dismiss itself.
this.modalCtl.dismiss();
  1. then you will see, both modal A and B are dismissed in the UI.
  2. and the page below can’t be interactive anymore.
  3. inspect DOM in devTools, you will see modal A is still there. And more strange is, you call interact with the buttons in modal A, although you can’t see it.

To find more, I try another test. Steps:

  1. create modal A, present it.
let modal = await this.modalCtl.create({
component: modalAClass
....
});
modal.present();
  1. in modal A, close A, and then create modal B.
this.modalCtl.getTop().dismiss();
let modal = await this.modalCtl.create({
component: modalBClass
....
});
modal.present();
  1. then you will see, both modal A and B are dismissed in the UI
  2. and the page below can’t be interactive anymore.
  3. inspect DOM in devTools, you will see modal B is still there. And as above, you call interact with the buttons in modal B, although you can’t see it.
  4. Workaround: add await before modalA dismiss, modal B will works. But, you will wait until modal A close before modalB popup, which is not a good UI expirence.

Envirorment: Ionic: Ionic CLI : 6.1.0 Ionic Framework : @ionic/angular 5.0.1 @angular-devkit/build-angular : 0.900.3 @angular-devkit/schematics : 9.0.3 @angular/cli : 9.0.3 @ionic/angular-toolkit : 2.1.2

Capacitor: Capacitor CLI : 1.5.0 @capacitor/core : 1.5.0

QQ20200225-193247@2x

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 4
  • Comments: 28 (6 by maintainers)

Most upvoted comments

Can everyone try the following dev build and let me know if it resolves the issue?

Ionic Angular npm i @ionic/angular@5.1.0-dev.202004011618.3123a31

Ionic React npm i @ionic/react@5.1.0-dev.202004011618.3123a31

Thanks for the issue. This has been resolved via https://github.com/ionic-team/ionic/pull/20940 and will be available in an upcoming release of Ionic Framework.

@liamdebeasi You save my day, I tried your solution and the multiple modals problem is solved 🥳

Can everyone try the following dev build and let me know if it resolves the issue?

> Ionic Angular
> `npm i @ionic/angular@5.1.0-dev.202004011618.3123a31`
> 
> Ionic React
> `npm i @ionic/react@5.1.0-dev.202004011618.3123a31`

@liamdebeasi Thanks for this. I will give it a try tomorrow morning (I would have done it already if I hadn’t forgotten my mobile in the office…)

@liamdebeasi Thank you so much for your comments. It’s always better to have the Ionic team to get bug fixed.

The stylesheets will be removed, as can be seen from my debugger. The logic is whenever a modal is removed from the DOM, cleanUpStyleSheets() will be called, the counter associated with the stylesheet will be decreased, and we will check whether the modal being destroyed is the last one that’s using the stylesheet. If it is, the stylesheet will be removed. If an animation stylesheet is in the DOM, it must has a counter of no less than 1, meaning at least one modal (or something) is still using the stylesheet. It’s sort of like the link count pattern used in Linux like file systems.

With such approach, I did observe that there are 3 or 4 animation stylesheets that persist in the DOM with ever-increasing counters, which means they have been attempted to create regularly. It’s reasonable to keep them in the DOM because they are used frequently. Of course this is based on my limited understanding of Ionic core. Perhaps the remaining stylesheet can lead to other conflicts that I don’t realise.

About the impact… it depends. There are still quite a lot of people using Android 7 or even earlier version mobiles (more than 60% in our case because our app focus on unskilled/ elder people) and we have to consider their experience.

Finally thanks again for your attention. Let’s together make Ionic better.

@WintonLi You dig out an important issue to us.

Finally I was able to identify the root cause of the issue. This is actually a bug that may have a wider impact than on modal pages on Android devices.

The Problem

Modal elements (and some other elements) share animation stylesheets that are created dynamically by createKeyframeStylesheet() in core/src/utils/animation/animation-utils.ts. These stylesheets are necessary for modals to display.

When a modal is destroyed, all associating animation stylesheets will be removed from DOM by the cleanUpStyleSheets() method in ionic/core/src/utils/animation/animation.ts, and the current method simply performs removal without checking whether the stylesheets are still in use by other elements.

It happens that when multiple modals are created, one on top of another, they have identically animating behaviour, and therefore they share the same set of animation stylesheets. When one is dismissed (probably the last opened one), all these stylesheets are gone, leaving the rest modals displayed improperly - in most cases, they become invisible.

Solution

I have tried to solve the problem by creating a fork: https://github.com/WintonLi/ionic/tree/fix-chained-modals where a counter has been used to record the number of modal elements that are using a stylesheet. The stylesheet will never be removed unless its counter reaches zero.

These two functions has been modified:

  1. createKeyframeStylesheet() in core/src/utils/animation/animation-utils.ts - a counter will be initialized to 1 whenever a stylesheet is created, and the counter will be increased by one whenever a new use is detected.
  2. cleanUpStyleSheets() in ionic/core/src/utils/animation/animation.ts - it decreases the counter when called, and removes the stylesheet if the counter becomes zero.

Tests

I am now testing it manually in the following environment and everything works fine:

Ionic CLI : 5.4.6 @ionic/angular 5.0.7 @angular-devkit/build-angular : 0.901.0-rc.0 @angular-devkit/schematics : 9.1.0-rc.0 @angular/cli : 9.1.0-rc.0 @ionic/angular-toolkit : 2.1.2

@capacitor/android: 1.5.1 @capacitor/core : 1.5.1 @capacitor/cli : 1.5.1

Pull request

@liamdebeasi If needed, I am happy to create a pull request for the fix. Please note that this bug may affect not only modals. Without the fix, I observed some shared animation stylesheets for non-modal elements got randomly removed, which may cause other problems. I would suggest fixing it as soon as possible.

For those who suffer much from the bug (like myself…) and cannot wait until the fix comes out, you can try the fork I created to build your local version of ionic. Building instructions can be found in the official repo, but I am happy to help. Please note that I cannot guarantee anything and I would recommend against using it for production.