Select2 doesn't work when embedded in a bootstrap modal

Ok, I've got it to work.

change

<div id="myModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
  <div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
    <h3 id="myModalLabel">Panel</h3>
  </div>
  <div class="modal-body" style="max-height: 800px">

to

<div id="myModal" class="modal hide fade" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
  <div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
    <h3 id="myModalLabel">Panel</h3>
  </div>
  <div class="modal-body" style="max-height: 800px">

(remove tabindex="-1" from modal)


For Select2 v4:

Use dropdownParent to attach the dropdown to the modal dialog, rather than the HTML body.

<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
        <h4 class="modal-title" id="myModalLabel">Modal title</h4>
      </div>
      <div class="modal-body">
        <select id="select2insidemodal" multiple="multiple">
          <option value="AL">Alabama</option>
            ...
          <option value="WY">Wyoming</option>
        </select>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Save changes</button>
      </div>
    </div>
  </div>
</div>


<script>

$(document).ready(function() {
  $("#select2insidemodal").select2({
    dropdownParent: $("#myModal")
  });
});

</script>

This will attach the Select2 dropdown so it falls within the DOM of the modal rather than to the HTML body (the default). See https://select2.org/dropdown#dropdown-placement


I found a solution to this on github for select2

https://github.com/ivaynberg/select2/issues/1436

For bootstrap 3, the solution is:

$.fn.modal.Constructor.prototype.enforceFocus = function() {};

Bootstrap 4 renamed the enforceFocus method to _enforceFocus, so you'll need to patch that instead:

$.fn.modal.Constructor.prototype._enforceFocus = function() {};

Explanation copied from link above:

Bootstrap registers a listener to the focusin event which checks whether the focused element is either the overlay itself or a descendent of it - if not it just refocuses on the overlay. With the select2 dropdown being attached to the body this effectively prevents you from entering anything into the the textfield.

You can quickfix this by overwriting the enforceFocus function which registers the event on the modal