Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Callback or Reliable API for Modal Transition Completion #41188

Open
2 tasks done
hhoweson opened this issue Jan 28, 2025 · 0 comments
Open
2 tasks done

Callback or Reliable API for Modal Transition Completion #41188

hhoweson opened this issue Jan 28, 2025 · 0 comments

Comments

@hhoweson
Copy link

hhoweson commented Jan 28, 2025

Prerequisites

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants