web-dev-qa-db-fra.com

Select2 ne fonctionne pas lorsqu'il est intégré à un modal bootstrap

Lorsque j'utilise un select2 (entrée) dans bootstrap modal, je ne peux rien taper dedans. C'est comme handicapé? En dehors du modal, select2 fonctionne bien.

enter image description here

Exemple de travail: 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>

et 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};
        }
    }
});

réponses:

ici vous pouvez trouver un rapide correctif

et voici la "bonne manière": Select2 ne fonctionne pas lorsqu'il est incorporé dans un modal bootstrap

308
breq

Ok, je l'ai pour travailler.

changement

<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">

à

<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">

(retirer tabindex = "- 1" de modal)

548
breq

Pour Select2 v4:

Utilisez dropdownParent pour associer la liste déroulante à la boîte de dialogue modale plutôt qu'au corps HTML.

<!-- 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>

Cela va associer la liste déroulante Select2 afin qu’elle tombe dans le DOM du modal plutôt que dans le corps HTML (valeur par défaut). Voir https://select2.org/dropdown#dropdown-placement

223
dboswell

J'ai trouvé une solution à cela sur github pour select2

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

Pour bootstrap 3, la solution est la suivante:

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

Bootstrap 4 a renommé la méthode enforceFocus en _enforceFocus, vous devrez donc appliquer un correctif à la place:

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

Explication copiée à partir du lien ci-dessus:

Bootstrap enregistre un écouteur dans l'événement focusin qui vérifie si l'élément ciblé est soit la superposition elle-même, soit un descendant de celle-ci - sinon, il se recentre simplement sur la superposition. Lorsque la liste déroulante select2 est attachée au corps, cela vous empêche en effet de saisir quoi que ce soit dans le champ de texte.

Vous pouvez résoudre ce problème rapidement en écrasant la fonction enforceFocus qui enregistre l’événement sur le serveur modal.

180
pymarco

Supprimez simplement tabindex="-1" et ajoutez le style overflow:hidden

Voici un exemple:

<div id="myModal" class="modal fade" role="dialog" style="overflow:hidden;">
    <!---content modal here -->
</div>
33
MrBii
.select2-close-mask{
    z-index: 2099;
}
.select2-dropdown{
    z-index: 3051;
}

Ceci est ma solution avec select2 4.0.0. Il suffit de remplacer le css juste en dessous de l’importation select2.css. Assurez-vous que l'indice z est supérieur à votre boîte de dialogue ou à votre modal. Je viens d'ajouter 2000 sur ceux par défaut. Parce que les z-index de mes dialogues sont environ 1000.

24
Diluka W

Définissez le dropdownParent. Je devais le définir sur le contenu modal dans le modal sinon le texte serait centré.

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

Réponse qui a fonctionné pour moi trouvé ici: https://github.com/select2/select2-bootstrap-theme/issues/41

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

Ne nécessite pas non plus la suppression de la tabindex.

9
Ashraf Slamang

J'ai eu le même problème, mettre à jour z-index pour .select2-container devrait faire l'affaire. Assurez-vous que le z-index de votre modal est inférieur à celui de select2.

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

Mise à jour: au cas où le code ci-dessus ne fonctionnerait pas correctement, supprimez également les tabindex de votre modal comme suggéré par @breq

7
hhk

Jusqu’à utiliser ce code sur Document.read ()

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

Juste pour mieux comprendre le fonctionnement des éléments tabindex pour compléter la réponse acceptée:

L'attribut global tabindex est un entier indiquant si l'élément peut prendre le focus en entrée (peut être mis au point), s'il doit participer à la navigation au clavier séquentielle et, dans l'affirmative, à quelle position. Cela peut prendre plusieurs valeurs:
- une valeur négative signifie que l'élément doit pouvoir être mis au point, mais ne doit pas être accessible via une navigation au clavier séquentielle;
-0 signifie que l'élément doit pouvoir être mis au point et accessible via une navigation au clavier séquentielle, mais son ordre relatif est défini par la convention de la plate-forme;
- une valeur positive signifie qu’il faut pouvoir mettre au point et être accessible via une navigation au clavier séquentielle; son ordre relatif est défini par la valeur de l'attribut: les valeurs séquentielles suivent le nombre croissant du tabindex. Si plusieurs éléments partagent le même tabindex, leur ordre relatif suit leur position relative dans le document.

à partir de: Mozilla Devlopper Network

5
538ROMEO

Ce problème a fonctionné pour moi Fonction Jquery unique

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

changer select2.css fichier

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

à

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

Selon la documentation officielle de select2, ce problème se pose car les modaux Bootstrap ont tendance à dérober le focus à d'autres éléments extérieurs au modal.

Par défaut, Select2 associe le menu déroulant à l'élément, qui est considéré comme "en dehors du modal".

Attachez plutôt le menu déroulant au modal lui-même avec le paramètre dropdownParent:

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

Voir la référence: https://select2.org/troubleshooting/common-problems

4
Anas

Basé sur la réponse de @pymarco, j’ai écrit cette solution, elle n’est pas parfaite mais résout le problème de la mise au point avec select2 et maintient la séquence de tabulation en mode 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))
    }
3
Angelo Cavalet
$("#IlceId").select2({
    allowClear: true,
    multiple: false,
    dropdownParent: $("#IlceId").parent(),
    escapeMarkup: function (m) {
        return m;
    },
});

ce code fonctionne. Je vous remercie.

2
ramazan polat

Si vous avez un problème avec le clavier iPad qui masque le bootstrap modal en cliquant sur l’entrée select2 , vous pouvez résoudre ce problème en ajoutant le règle suivante après l'initialisation de l'entrée select2:

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
}

Extrait de https://github.com/angular-ui/bootstrap/issues/1812#issuecomment-135119475

EDIT: Si vos options ne sont pas affichées correctement, vous devez utiliser l'attribut dropdownParent lors de l'initialisation de select2:

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

Bonne chance (:

2
Gangai Johann

Ok, je sais que je suis en retard à la fête. Mais laissez-moi partager avec vous ce qui a fonctionné pour moi. Les solutions tabindex et z-index ne fonctionnaient pas pour moi.

La définition du parent de l’élément select a fonctionné comme indiqué dans le problèmes courants répertoriés sur le site select2.

2
joker

J'ai le même problème avec le select2 dans bootstrap modal, et la solution a été de supprimer le overflow-y: auto; et overflow: hidden; de .modal-open et .modal classes

Voici l'exemple d'utilisation de jQuery pour supprimer le overflow-y:

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

j'avais ce problème auparavant, j'utilise yii2 et je l'ai résolu de cette façon

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

J'avais un problème semi-lié dans une application donc je vais mettre dans mon 2c.

J'ai plusieurs modaux avec des formulaires contenant des widgets select2. Ouvrir modal A, puis un autre modal à l'intérieur de modal A, ferait disparaître les widgets select2 à l'intérieur de modal B et ne pourrait pas s'initialiser.

Chacun de ces modaux chargeait les formulaires via ajax.

La solution consistait à supprimer les formulaires du dom lors de la fermeture d'un modal.

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

J'ai généralement résolu ce problème dans mon projet en surchargeant la fonction select2-. Maintenant, il va vérifier s'il n'y a pas de dropdownParent et si la fonction est appelée sur un élément ayant un parent de type div.modal. Si tel est le cas, il ajoutera ce modal en tant que parent du menu déroulant.

De cette façon, vous n'avez pas à le spécifier chaque fois que vous créez une zone 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];
    }
})();
1
Zombaya

Si vous utilisez jquery mobile popup, vous devez réécrire la fonction _handleDocumentFocusIn:

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

Je viens de le faire fonctionner en incluant select2.min.css

Essaye le

Mon code HTML modal de bootstrap 3 est

<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>
0
Developer
$('.modal').on('shown.bs.modal', function (e) {
    $(this).find('.select2me').select2({
        dropdownParent: $(this).find('.modal-content')
    });
})
0
ocobacho