Callback or Reliable API for Modal Transition Completion
Nobody has claimed this yet.
- Dominant language
- MDX
- Stars
- 175k
- Forks
- 78.6k
- Avg merge
- 7h 19m
- Merged PRs (30d)
- 35
Description
Prerequisites
- I have searched for duplicate or closed feature requests
- I have read the contributing guidelines
Proposal
I want to show/hide a bootstrap modal and get a callback when the animation has finished. I know this seems simple but bear with me.
For the sake of simplifying the explanation i'm going to focus on the issue of opening a bootstrap modal since the problem is fundamentally the same for both opening and closing the modal.
There are no callbacks on the show/hide methods so the only way to tell when a transition has finished is with the hidden.bs.modal or shown.bs.modal events. Given this, the obvious approach to opening a bootstrap modal and waiting until it has finished would be something like this:
function showModal($modal){
return new Promise(function(resolve){
$modal.one('shown.bs.modal', function(){
resolve();
});
$modal.modal('show');
});
};
The problem with this is that the shown.bs.modal event does not fire if the modal is already shown. As a result this promise would never resolve if the modal was already shown. The obvious solution to this is checking whether the bootstrap modal is shown before registering the event:
function showModal($modal){
return new Promise(function(resolve){
if ($modal.hasClass('show')) {
resolve();
} else {
$modal.one('shown.bs.modal', function(){
resolve();
});
$modal.modal('show');
}
});
};
This will:
- Resolve if the modal is already shown
- If the modal is hidden it will show the modal, wait for the transition, and then reslove
Unfortunately the show class is applied immediately when .modal('show') is called. This means that if this method were to be called during a transition it would resolve immediately (before the transition had finished) which is undesired behaviour in this case.
The reason it's so important to reliably tell when a modal has finished transitioning is because the .modal('hide/show') commands will be ignored until bootstrap thinks the transition has completed. As it is there is no reliable way for a script to ensure that a modal is closed before possibly re-opening the modal with different content.
This problem is made harder to solve by the fact that bootstrap uses custom logic to determine if a modal is transitioning. This includes adding a 5ms buffer to the expected transition time. This means that determining the transition state outside of bootstrap is impossible because that 5ms buffer is presumably subject to change in future releases.
I'm not sure what to suggest in terms of a solution as it depends greatly on the design philosophy. But any one of the below options would make this problem significantly easier to solve:
- A done callback for
.modal('show/hide') - A promise based method eg.
.modal.show().then(() => { ... }) - A way to track whether bootstrap thinks the modal is transitioning eg.
.modal.isTransitioning() - A way to determine if a bootstrap modal is fully shown/hidden eg.
.modal.isFullyShown()
Thank you for taking the time to read this.
Motivation and context
I want to be able to close a modal, wait till it has closed, and then reopen it with different content. I cannot guarantee that scripts outside of my control won't toggle the modal and as a result have no way of reliably determining the modals state.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with Bootstrap's modal show/hide methods, shown.bs.modal and hidden.bs.modal events, and its transition-state handling. Define and validate a reliable completion signal for already-visible modals and calls made during transitions, covering both opening and closing before settling on an API.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- frontend
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100