[twitter-bootstrap] Twitter bootstrap modal-backdrop doesn't disappear

I am using the Twitter bootstrap Modal dialog. When I click on the submit button of the bootstrap modal dialog, it sends an AJAX request. My problem is that the modal-backdrop doesn't disappear. The Modal dialog does disappear correctly, but instead "modal-backdrop in" that creates the opacity on the screen remain

What can I do?

This question is related to twitter-bootstrap modal-dialog

The answer is


I had a similar problem. I was using Boostrap in conjunction with Backbone, and I was capturing clicks of the "Do it" button, and then stopping propagation of those events. Bizarrely, this made the modal go away, but not the background. If I call event.preventDefault() but do not call stopPropagation(), it all works fine.


I had the same problem when trying to submit the form. The solution was to change the button type from submit to button and then handle the button click event like so:

'click .js-save-modal' () {
    $('#myFormId').submit();
    $('#myModalId').modal('hide');
}

I suffered a similar issue: in my modal window, I have two buttons, "Cancel" and "OK". Originally, both buttons would close the modal window by invoking $('#myModal').modal('hide') (with "OK" previously executing some code) and the scenario would be the following:

  1. Open the modal window
  2. Do some operations, then click on "OK" do validate them and close the modal
  3. Open the modal again and dismiss by clicking on "Cancel"
  4. Re-open the modal, click again on "Cancel" ==> the backdrop is no longer accessible!

well, my fellow next desk saved my day: instead of invoking $('#myModal').modal('hide'), give your buttons the attribute data-dismiss="modal" and add a "click" event to your "Submit" button. In my problem, the HTML (well, TWIG) code for the button is:

<button id="modal-btn-ok" class="btn" data-dismiss="modal">OK</button>
<button id="modal-btn-cancel" class="btn" data-dismiss="modal">Cancel</button>

and in my JavaScript code, I have:

$("#modal-btn-ok").one("click", null, null, function(){
    // My stuff to be done
});

while no "click" event is attributed to the "Cancel" button. The modal now closes properly and lets me play again with the "normal" page. It actually seems that the data-dismiss="modal" should be the only way to indicate that a button (or whatever DOM element) should close a Bootstrap modal. The .modal('hide') method seems to behave in a not quite controllable way.

Hope this helps!


This solution is for Ruby on Rails 3.x and a js.erb file that rebuilds part of the DOM including the modal. It works regardless if the ajax call came from the modal or from a different part of the page.

if ($("#my-modal").attr("aria-hidden") === "false") {
  $("#my-modal").modal('hide').on('hidden.bs.modal', function (event) {
    functionThatEndsUpDestroyingTheDOM();
  });
} else {
  functionThatEndsUpDestroyingTheDOM();
}

Thanks to @BillHuertas for the starting point.


This problem can also occur if you hide and then show again the modal window too rapidly. This was mentioned elsewhere for question, but I'll provide some more detail below.

The problem has to do with timing, and the fade transition. If you show a modal before the fade out transition for the previous modal is complete, you'll see this persistent backdrop problem (the modal backdrop will stay on the screen, in your way). Bootstrap explicitly does not support multiple simultaneous modals, but this seems to be a problem even if the modal you're hiding and the modal you're showing are the same.

If this is the correct reason for your problem, here are some options for mitigating the issue. Option #1 is a quick and easy test to determine if the fade transition timing is indeed the cause of your problem.

  1. Disable the Fade animation for the modal (remove the "fade" class from the dialog)
  2. Update the modal's text instead of hiding and re-showing it.
  3. Fix the timing so that it won't show the modal until it's finished hiding the previous modal. Use the modal's events to do this. http://getbootstrap.com/javascript/#modals-events

Here are some related bootstrap issue tracker posts. It is possible that there are more tracker posts than I've listed below.


Even I ran into a similar problem, I had the following two buttons

<button id="confirm-delete-btn" >Yes, Delete this note.</button>
<button id="confirm-delete-cancel" data-dismiss="modal">No</button>

I wanted to perform some ajax operation and on success of that ajax operation close the modal. So here is what I did.

$.ajax({
        url: '/ABC/Delete/' + self.model.get("Id")
            , type: 'DELETE'
            , success: function () {                    
                setTimeout(function () {
                    self.$("#confirm-delete-cancel").trigger("click");
                }, 1200);
            }
            , error: function () {}
        });

I triggered the click event of the 'No' button which had the data-dismiss="modal" property. And this worked :)


the initial value of your data-backdrop attribute can be

"static","true", "false" .

static and true add the modal shadow, while false disable the shadow, so you just need to change this value with the first click to false . like this:

_x000D_
_x000D_
$(document).on('ready',function(){_x000D_
 _x000D_
 var count=0;_x000D_
 _x000D_
$('#id-which-triggers-modal').on('click',function(){_x000D_
  _x000D_
  if(count>0){_x000D_
  _x000D_
   $(this).attr('data-backdrop','false')_x000D_
  }_x000D_
  count++;_x000D_
});_x000D_
_x000D_
_x000D_
});
_x000D_
_x000D_
_x000D_


In ASP.NET, add an update for UpdatePanel on code behind after the jquery command. Example:

    ScriptManager.RegisterStartupScript(Page, Page.GetType(), "myModal", "$('#myModal').modal('hide');", true);
    upModal.Update();

From https://github.com/twbs/bootstrap/issues/19385

Modal's show/hide methods are asynchronous. Therefore, code such as:

foo.modal("hide"); bar.modal("show"); is invalid. You need to wait for the showing/hiding to actually complete (by listening for the shown/hidden events; see http://getbootstrap.com/javascript/#modals-events ) before calling the show or hide methods again.

I had this problem when I opened the same modal twice too fast, so an easy fix was checking if it was already shown, then to not show it again:

$('#modalTitle').text(...);
$('#modalMessage').text(...);
if($('#messageModal').is(':hidden')){
    $('#messageModal').modal('show');
}

Adding data-dismiss="modal" on any buttons in my modal worked for me. I wanted my button to call a function with angular to fire an ajax call AND close the modal so I added a .toggle() within the function and it worked well. (In my case I used a bootstrap modal and used some angular, not an actual modal controller).

<button type="button" class="btn btn-primary" data-dismiss="modal"
ng-click="functionName()"> Do Something </button>

$scope.functionName = function () {
angular.element('#modalId').toggle();
  $.ajax({ ajax call })
}

I am working with Meteor and I just got the same problem. The cause of my bug was this:

{{#if tourmanager}}
    {{>contactInformation tourmanager}}
{{else}}
    <a href="#addArtistTourmanagerModal" data-toggle="modal"><i class="fa fa-plus"></i> Tourmanager toevoegen</a>
    {{>addArtistTourmanagerModal}}
{{/if}}

As you can see I added the modal in the else, so when my modal updated the contactinformation the if had another state. This caused the modal template to be left out of the DOM just before it would close.

The solution: move the modal out of the if-else:

{{#if tourmanager}}
    {{>contactInformation tourmanager}}
{{else}}
    <a href="#addArtistTourmanagerModal" data-toggle="modal"><i class="fa fa-plus"></i> Tourmanager toevoegen</a>
    {{>addArtistTourmanagerModal}}
{{/if}}

I had the modal backdrop screen freeze problem but in a slightly different scenario: When 2 back to back modals were being displayed. e.g. The first would ask for confirmation to do something and after the 'confirm' button was clicked, the action would come across an error and the 2nd modal was going to be displayed to popup the error message. The 2nd modal backdrop would freeze the screen. There were no clashes in class names or id's of the elements.

The way the problem was fixed was to give the browser enough time to deal with the modal backdrop. Instead of immediately taking the action after the 'confirm' was clicked, give the browser say 500ms to hide the 1st modal and clean up the backdrop etc - then take the action which would end up in showing the error modal.

<button type="button" class="btn btn-red" data-dismiss="modal" on-tap="_dialogConfirmed">Confirm</button>
...

The _dialogConfirmed() function has the following code:

    var that = this;

    setTimeout(function () {
      if (that.confirmAction) {
        (that.confirmAction)();
        that.confirmAction = undefined;
      }
    }, 500);

I'm guessing the other solutions worked because they took enough extra time giving the browser the needed cleanup time.


for me, the best answer is this.

<body>
<!-- All other HTML -->
<div>
    ...
</div>

<!-- Modal -->
<div class="modal fade" id="myModal">
    ...
</div>

Modal Markup Placement Always try to place a modal's HTML code in a top-level position in your document to avoid other components affecting the modal's appearance and/or functionality.

from this SO answer


This Line of Code after many search solved my problem, that i wanted to close the modal on ajax success:

$('#exampleModal').modal('hide');
$("[data-dismiss=modal]").trigger({ type: "click" });

Many thanks, Manuel Fernando https://stackoverflow.com/a/27218322/5935763


I had the same problem. I discovered it was due to a conflict between Bootstrap and JQueryUI.

Both use the class "close". Changing the class in one or the other fixes this.


Using toggle instead of hide, solved my problem


Recently I had this problem and none of solutions provided here helped me. Or it completely destroyed it so it could not be shown again. On document ready also did not work but what worked is that I wrapped all my listeners with immediately invoked function like this:

$(function () {
    $('#btn-show-modal').click(function () {
        $("#modal-lightbox").modal('show');
    });

    $('#btn-close-modal').click(function () {
        $("#modal-lightbox").modal('hide');
    });
});

In .net MVC4 project I had the modal pop up (bootstrap 3.0) inside an Ajax.BeginForm( OnComplete = "addComplete" [extra code deleted]). Inside the "addComplete" javascript I had the following code. This solved my issue.

$('#moreLotDPModal').hide();

$("#moreLotDPModal").data('bs.modal').isShown = false;

$('body').removeClass('modal-open');

$('.modal-backdrop').remove();

$('#moreLotDPModal').removeClass("in");

$('#moreLotDPModal').attr('aria-hidden', "true");


.modal('hide')

Manually hides a modal. Returns to the caller before the modal has actually been hidden (i.e. before the hidden.bs.modal event occurs).

So instead of

$('#myModal').modal('hide');
$('#someOtherSelector').trigger('click');

do

$('#myModal').modal('hide');
$('#myModal').on('hidden.bs.modal', function() {
   $('#someOtherSelector').trigger('click');
});

So you are sure to wait till the "hide" event is finished.


FYI in case someone runs into this still... I've spent about 3 hours to discover that the best way to do it is as follows:

$("#my-modal").modal("hide");
$("#my-modal").hide();
$('.modal-backdrop').hide();
$("body").removeClass("modal-open");

That function to close the modal is very unintuitive.


I had this very same issue.

However I was using bootbox.js, so it could have been something to do with that.

Either way, I realised that the issue was being caused by having an element with the same class as it's parent. When one of these elements is used to bind a click function to display the modal, then the problem occurs.

i.e. this is what causes the problem:

<div class="myElement">
    <div class="myElement">
        Click here to show modal
    </div>
</div>

change it so that the element being clicked on doesn't have the same class as it's parent, any of it's children, or any other ancestors. It's probably good practice to do this in general when binding click functions.


Make sure that your initial call to $.modal() to apply the modal behavior is not passing in more elements than you intended. If this happens, it will end up creating a modal instance, complete with backdrop element, for EACH element in the collection. Consequently, it might look like the backdrop has been left behind, when actually you're looking at one of the duplicates.

In my case, I was attempting to create the modal content on-the-fly with some code like this:

myModal = $('<div class="modal">...lots of HTML content here...</div><!-- end modal -->');
$('body').append(myModal);
myModal.modal();

Here, the HTML comment after the closing </div> tag meant that myModal was actually a jQuery collection of two elements - the div, and the comment. Both of them were dutifully turned into modals, each with its own backdrop element. Of course, the modal made out of the comment was invisible apart from the backdrop, so when I closed the real modal (the div) it looked like the background was left behind.


Another possible mistake that could produce this problem,

Make sure you didn't included bootstrap.js script more than once in your page!


use:

$('.modal.in').modal('hide') 

Source


Make sure you are not using the same element Id / class elsewhere, for an element unrelated to the modal component.

That is.. if you are identifying your buttons which trigger the modal popups using the class name 'myModal', ensure that there are no unrelated elements having that same class name.


Another point of view to this question. (I'm using the bootstrap.js version 3.3.6)

I mistaken initialize modal both by manually in javascript:

$('#myModal').modal({
   keyboard: false
})

and by using

data-toggle="modal"

in this button like example below (shown in document)

<button type="button" class="btn btn-primary btn-lg" data-toggle="modal" data-target="#myModal">Launch demo modal</button>

so the result its create two instance of

<div class="modal-backdrop fade in"></div>

append to the body of my html when open the modal. This can be the cause when closing the modal by using function:

$('#myModal').modal('hide');

it remove only one backdrop instance (as show above) so the backdrop won't disappeared. But it did disappear if you use data-dismiss="modal" add on html as show in bootstrap doc.

So the solution to my problem is to only initialize modal manually in javascript and not using data attribute, In this way I can both close the modal manually and by using data-dismiss="modal" features.

Hope this will help if you encountered the same problem as me.


Insert in your action button this:

data-backdrop="false"

and

data-dismiss="modal" 

example:

<button type="button" class="btn btn-default" data-dismiss="modal">Done</button>

<button type="button" class="btn btn-danger danger" data-dismiss="modal" data-backdrop="false">Action</button>

if you enter this data-attr the .modal-backdrop will not appear. documentation about it at this link :http://getbootstrap.com/javascript/#modals-usage


After applying the top rated solution I've had a problem that it breaks future modals opening properly. I've found my solution which works good

        element.on("shown.bs.modal", function () {
            if ($(".modal-backdrop").length > 1) {
                $(".modal-backdrop").not(':first').remove();
            }
            element.css('display', 'block');
        });

$('#myModal').trigger('click');

This worked for me. Its not closing because when you open the popup it triggers 2 or 3 modal-backdrops. So when you do $('#myModal')).modal('hide'); it only effect one modal-backdrop and rest remains.


Try this

$('#something_clickable').on('click', function () {
  $("#my_modal").modal("hide");
  $("body").removeClass("modal-open");
  $('.modal-backdrop').remove();
 });

It works fine for me.


//Create modal appending on body
myModalBackup = null;
$('#myModal').on('hidden.bs.modal', function(){
       $('body').append(myModalBackup.clone());
    myModalBackup = null;
});

//Destroy, clone and show modal
myModalBackup = $('#myModal').clone();
myModalBackup.find('.modal-backdrop').remove();
$('#myModal').modal('hide').remove();
myModalBackup.find('.info1').html('customize element <b>1</b>...');
myModalBackup.find('.info2').html('customize element <b>2</b>...');                             
myModalBackup.modal('show');

fiddle --> https://jsfiddle.net/o6th7t1x/4/


I know this is a very old post but this might help. This is a very small workaround by me

$('#myModal').trigger('click');

Thats it, This should solve the issue


updatepanel issue.

My issue was due to the updatepanel placement. I had the entire modal in the updatepanel. If you declare the modal outside the updatepanel and just have say, the modal body, in the update panel, then the $('#myModalID').modal('hide'); worked.


If you are using a copy and paste from the getboostrap site itself into an html generated selector, make sure you remove the comment '<!-- /.modal -->'. Bootstrap gets confused and thinks that the comment is a second modal element. It creates another back drop for this "second" element.


I just spent way too long on this problem :)

While the other answers provided are helpful and valid, it seemed a little messy to me to effectively recreate the modal hiding functionality from Bootstrap, so I found a cleaner solution.

The problem is that there are a chain of events that happen when you call

$("#myModal").modal('hide');
functionThatEndsUpDestroyingTheDOM()

When you then replace a bunch of HTML as the result of the AJAX request, the modal-hiding events don't finish. However, Bootstrap triggers an event when everything is finished, and you can hook into that like so:

$("#myModal").modal('hide').on('hidden.bs.modal', functionThatEndsUpDestroyingTheDOM);

Hope this is helpful!