bug: Overlays dismiss() method can cause getTop() to return dismissed instance
See original GitHub issuePrerequisites
- I have read the Contributing Guidelines.
- I agree to follow the Code of Conduct.
- I have searched for existing issues that already report this problem, without success.
Ionic Framework Version
- v4.x
- v5.x
- v6.x
- Nightly
Current Behavior
I want to show a loading screen while my (Angular) app navigates. I solve this by adding and removing a loading screen (via LoadingController) on navigation start and navigation end (as well as cancel and error).
It usually works, but:
I have a parent route w/ children routes. The parent route redirects the user to a specific child (the first) each time it’s loaded. That means, if the user refreshes the browser when standing on another child than the first, the parent route loads first and redirects them to the first child. Standard stuff. Let me just say that there’s no indication that this is what’s causing the problem, just consider it context.
This is the service method that should close the loading indicator(s):
private closeLoadingIndicators(): void {
this.loadingController.getTop().then((loadingIndicator: HTMLIonLoadingElement | undefined) => {
console.log('loadingIndicator:', loadingIndicator);
console.log('undefined:', loadingIndicator === undefined);
console.log('typeof:', typeof loadingIndicator);
console.log('present:', loadingIndicator?.present);
console.log('Removing loading screen');
if (loadingIndicator) {
loadingIndicator.dismiss().then(() => {
this.closeLoadingIndicators();
});
}
})
}
The idea is that the DOM can have several loading indicator present, and as long as it has, remove them one by one.
The output from the console.log()
s are as following:
As you can see, the ‘loadingIndicator’ is nothing(?), but the type seems to be object
.
Even though the instance seems to be nothing, the if check renders true, and the app re-runs the method, causing an endless loop.
Not sure what’s causing it, and the reason why I gave the context of my app routes, is because it only happens on that particular navigation (with the redirect). It does not seem to be relevant though. What does seem to be relevant, is time. When doing something like this:
from(loadingIndicator.dismiss()).pipe(
delay(300),
tap(() => {
this.closeLoadingIndicators();
})).subscribe();
…everything seems to work fine. Which leads me to think that even though the LoadingController.dismiss()
promise is resolved, maybe the HTML element isn’t really removed from the DOM yet.
I don’t know, I can’t get further with this. Anyone?
Expected Behavior
The LoadingController.getTop() to return either the HTML element or undefined (like it’s typed)
Steps to Reproduce
See the code reproduction url
Code Reproduction URL
https://stackblitz.com/edit/ionicon-title-bug-1wtfct?file=src/app/app.component.ts
Ionic Info
Ionic:
Ionic CLI : 6.17.0
Utility:
cordova-res : not installed globally native-run : not installed globally
System:
NodeJS : v14.17.5 npm : 7.21.1 OS : Linux 5.13
Additional Information
No response
Issue Analytics
- State:
- Created a year ago
- Comments:8 (5 by maintainers)
Top GitHub Comments
@andreaslarssen in theory it applies to all overlays (alerts, loading, modal, popover, etc.). The resolution will be to the shared dismiss logic that each of the overlay implementations use.
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.