Select2 doesn't work when embedded in a bootstrap modal

孤者浪人 提交于 2019-11-26 04:29:41

问题


When I use a select2 (input) in bootstrap modal, I can\'t type anything into it. It\'s like disabled? Outside the modal select2 works fine.

\"enter

Working example: http://jsfiddle.net/byJy8/1/ code:

<!-- Modal -->
<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\">


<form class=\"form-horizontal\">

<!-- Text input-->
<div class=\"control-group\">
  <label class=\"control-label\" for=\"vdn_number\">Numer</label>
  <div class=\"controls\">
     <!-- seleect2 -->
    <input name=\"vdn_number\" type=\"hidden\" id=\"vdn_number\"  class=\"input-large\" required=\"\"  />
  </div>
</div>

  </div>
  <div class=\"modal-footer\">
    <button class=\"btn\" data-dismiss=\"modal\" aria-hidden=\"true\">Close</button>
    <button class=\"btn btn-primary\">Save changes</button>
  </div>
</div>

and js:

$(\"#vdn_number\").select2({
    placeholder: \"00000\",
    minimumInputLength: 2,
    ajax: {
        url: \"getAjaxData/\",
        dataType: \'json\',
        type: \"POST\",
        data: function (term, page) {
            return {
                q: term, // search term
                col: \'vdn\'
            };
        },
        results: function (data) { // parse the results into the format expected by Select2.
            // since we are using custom formatting functions we do not need to alter remote JSON data
            return {results: data};
        }
    }
});

answers:

here you can find a quick fix

and here is \'the right way\': Select2 doesn't work when embedded in a bootstrap modal


回答1:


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)




回答2:


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




回答3:


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




回答4:


Just remove tabindex="-1" and add style overflow:hidden

Here is an example:

<div id="myModal" class="modal fade" role="dialog" style="overflow:hidden;">
    <!---content modal here -->
</div>



回答5:


.select2-close-mask{
    z-index: 2099;
}
.select2-dropdown{
    z-index: 3051;
}

This is my solution with select2 4.0.0. Just override the css right below the select2.css import. Please make sure the z-index is greater than your dialog or modal. I just add 2000 on the default ones. Cause my dialogs' z-index are about 1000.




回答6:


Set the dropdownParent. I had to set it on .modal-content within the modal or the text would end up centered.

$("#product_id").select2({
    dropdownParent: $('#myModal .modal-content')
});



回答7:


Answer that worked for me found here: https://github.com/select2/select2-bootstrap-theme/issues/41

$('select').select2({
    dropdownParent: $('#my_amazing_modal')
});

Also doesn't require removing the tabindex.




回答8:


I had the same issue, updating z-index for .select2-container should do the trick. Make sure your modal's z-index is lower than select2's.

.select2-container {
    z-index: 99999;
}

Updated: In case above code doesn't work properly, also remove tabindexes from your modal as @breq suggested




回答9:


According to the official select2 documentation this issue occurs because Bootstrap modals tend to steal focus from other elements outside of the modal.

By default Select2 attaches the dropdown menu to the element and it is considered "outside of the modal".

Instead attach the dropdown to the modal itself with the dropdownParent setting:

$('#myModal').select2({
   dropdownParent: $('#myModal')
});

See reference: https://select2.org/troubleshooting/common-problems




回答10:


Jus use this code on Document.read()

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



回答11:


This Problem Sloved Working For Me Single Jquery Function

$('#myModal .select2').each(function() {  
   var $p = $(this).parent(); 
   $(this).select2({  
     dropdownParent: $p  
   });  
});



回答12:


change select2.css file

z-index: 9998;
...
z-index: 9999;
...
z-index: 10000;

to

z-index: 10000;
...
z-index: 10001;
...
z-index: 10002;



回答13:


Just to understand better how tabindex elements works to complete accepted answer :

The tabindex global attribute is an integer indicating if the element can take input focus (is focusable), if it should participate to sequential keyboard navigation, and if so, at what position. It can take several values:
  -a negative value means that the element should be focusable, but should not be reachable via sequential keyboard navigation;
  -0 means that the element should be focusable and reachable via sequential keyboard navigation, but its relative order is defined by the platform convention;
  -a positive value means should be focusable and reachable via sequential keyboard navigation; its relative order is defined by the value of the attribute: the sequential follow the increasing number of the tabindex. If several elements share the same tabindex, their relative order follows their relative position in the document.

from : Mozilla Devlopper Network




回答14:


Based on @pymarco answer I wrote this solution, it's not perfect but solves the select2 focus problem and maintain tab sequence working inside modal

    $.fn.modal.Constructor.prototype.enforceFocus = function () {
        $(document)
        .off('focusin.bs.modal') // guard against infinite focus loop
        .on('focusin.bs.modal', $.proxy(function (e) {
            if (this.$element[0] !== e.target && !this.$element.has(e.target).length && !$(e.target).closest('.select2-dropdown').length) {
                this.$element.trigger('focus')
            }
        }, this))
    }



回答15:


$("#IlceId").select2({
    allowClear: true,
    multiple: false,
    dropdownParent: $("#IlceId").parent(),
    escapeMarkup: function (m) {
        return m;
    },
});

this code is working. Thank you.




回答16:


If you have a problem with the iPad keyboard which hide the bootstrap modal while clicking on the select2 input, you can resolve this by adding the following rule after the initialization of the select2 input :

if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) {
   var styleEl = document.createElement('style'), styleSheet;
   document.head.appendChild(styleEl);
   styleSheet = styleEl.sheet;
   styleSheet.insertRule(".modal { position:absolute; bottom:auto; }", 0);
   document.body.scrollTop = 0; // Only for Safari
}

Taken from https://github.com/angular-ui/bootstrap/issues/1812#issuecomment-135119475

EDIT: If your options are not shown properly, you need to use the dropdownParent attribute when initializing select2 :

$(".select2").select2({
    dropdownParent: $("#YOURMODALID")
});

Good luck (:




回答17:


Okay, I know I'm late to the party. But let me share with you what worked for me. The tabindex and z-index solutions did not work for me.

Setting the parent of the select element worked as per the common problems listed on select2 site.




回答18:


If you use jquery mobile popup you must rewrite _handleDocumentFocusIn function:

$.mobile.popup.prototype._handleDocumentFocusIn = function(e) {
  if ($(e.target).closest('.select2-dropdown').length) return true;
}



回答19:


I have the same problem with the select2 in bootstrap modal, and the solution was to remove the overflow-y: auto; and overflow: hidden; from .modal-open and .modal classes

Here is the example of using jQuery to remove the overflow-y:

$('.modal').css('overflow-y','visible');
$('.modal').css('overflow','visible');



回答20:


i had this problem before , i am using yii2 and i solved it this way

$.fn.modal.Constructor.prototype.enforceFocus = $.noop;



回答21:


I had a semi-related issue in an application so I'll put in my 2c.

I have multiple modals with forms containing select2 widgets. Opening modal A, then another modal inside modal A, would cause select2 widgets inside modal B to disappear and fail to initialize.

Each of these modals were loading the forms via ajax.

The solution was to remove the forms from the dom when closing a modal.

$(document).on('hidden.bs.modal', '.modal', function(e) {
    // make sure we don't leave any select2 widgets around 
    $(this).find('.my-form').remove();
});



回答22:


$('.modal').on('shown.bs.modal', function (e) {
    $(this).find('.select2me').select2({
        dropdownParent: $(this).find('.modal-content')
    });
})



回答23:


I solved this generally in my project by overloading the select2-function. Now it will check if there is no dropdownParent and if the function is called on an element that has a parent of the type div.modal. If so, it will add that modal as the parent for the dropdown.

This way, you don't have to specify it every time you create a select2-input-box.

(function(){
    var oldSelect2 = jQuery.fn.select2;
    jQuery.fn.select2 = function() {
        const modalParent = jQuery(this).parents('div.modal').first();
        if (arguments.length === 0 && modalParent.length > 0) {
            arguments = [{dropdownParent: modalParent}];
        } else if (arguments.length === 1
                    && typeof arguments[0] === 'object'
                    && typeof arguments[0].dropdownParent === 'undefined'
                    && modalParent.length > 0) {
            arguments[0].dropdownParent = modalParent;
        }
        return oldSelect2.apply(this,arguments);
    };
    // Copy all properties of the old function to the new
    for (var key in oldSelect2) {
        jQuery.fn.select2[key] = oldSelect2[key];
    }
})();



回答24:


I just get it working by including select2.min.css

Try iy out

My modal html of bootstrap 3 is

<div id="changeTransportUserRequestPopup" class="modal fade" role="dialog">
    <div class="modal-dialog" style="width: 40%!important; ">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal">&times;</button>
                <h3>Warning</h3>
            </div>
            <div class="modal-body" id="changeTransportUserRequestPopupBody">
                <select id="cbTransport" class="js-example-basic-single" name="cbTransport" style="width:100%!important;"></select>
            </div>
            <div class="modal-footer">
                <button id="noPost" class="btn btn-default" name="postConfirm" value="false" data-dismiss="modal">Cancel</button>
                <button type="submit" id="yesChangeTransportPost" class="btn btn-success" name="yesChangeTransportPost" value="true" data-dismiss="modal">Yes</button>
            </div>
        </div>
    </div>
</div>



回答25:


In my case I had the same problem with two modals and all was resolved using:

$('.select2').each(function() { 
    $(this).select2({ dropdownParent: $(this).parent()});
})

As in the project issue #41 an user said.




回答26:


In my case i did this and it works. I use bundle to load it and in this case it worked for me

 $(document).on('select2:select', '#Id_Producto', function (evt) {
   // Here your code...
  });


来源:https://stackoverflow.com/questions/18487056/select2-doesnt-work-when-embedded-in-a-bootstrap-modal

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!