Select2 ne fonctionne pas lorsqu'il est intégré dans un modal d'amorçage


338

Lorsque j'utilise un select2 (entrée) en mode bootstrap, je ne peux rien y taper. C'est comme handicapé? En dehors du modal select2 fonctionne très bien.

entrez la description de l'image ici

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:

Vous pouvez trouver une rapide solution

et voici «la bonne façon»: Select2 ne fonctionne pas lorsqu'il est intégré dans un modal bootstrap


1
Autrement dit, supprimer l'attribut tabindex = "- 1" de l'élément.
Nikit Barochiya du

La réponse de dboswell est la bonne solution, MAIS, le dropdownParentne devrait pas être sur le div racine, mais plus profond, par exemple le div avec classe modal-content, sinon les positions déroulantes sont gâchées lors du défilement du modal.
Shahin Dohan

Réponses:


606

Ok, je dois le faire fonctionner.

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

(supprimer tabindex = "- 1" du modal)


22
Peut-il y avoir une autre solution? Parce que la fenêtre modale ne se fermera pas par la touche Echap.
woto

19
la suppression de tabindex = "- 1" n'a pas fonctionné depuis moi. Je viens de changer <div class = "modal-body"> en <div class = "modal-body" style = "overflow: hidden;">
Wissem

39
Comment diable avez-vous découvert cela?
DontVoteMeDown

6
J'ai essayé toutes les options, mais rien ne fonctionne pour moi. J'utilise select2 4.0
Girish Gupta

7
Merci! Cela fait 4 ans et c'est toujours une solution valable.
Linek

248

Pour Select2 v4:

Utilisez dropdownParentpour attacher 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 attachera la liste déroulante Select2 afin qu'elle tombe dans le DOM du modal plutôt que dans le corps HTML (par défaut). Voir https://select2.org/dropdown#dropdown-placement


12
Confirmé, cela fonctionne comme un charme et semble être la meilleure solution à ce problème!
lacco

29
Cela a fonctionné pour moi (avec v4.0.2), mais je devais l'utiliser dropdownParent: $("#myModal"), non dropdownParent: "#myModal".
Saxon Druce

6
FWIW, dans mon cas, je devais définir le dropdownParent sur le corps du modal, l'attacher au modal lui-même n'a pas élevé le z-index suffisamment haut. par exemple dropdownParent: $ ('. modal-body', '#myModal')
DrewInTheMountains

1
Cela fonctionne parfaitement bien sans supprimer tabindex. +1
sammry

1
@DrewInTheMountains J'ai également eu des problèmes pour définir le dropdownParentà la racine du modal, il est en effet préférable de choisir le corps, sinon vous obtenez de très mauvais bugs de positionnement lors du défilement. J'ai mis le mien au div avec classe modal-contentet ça marche comme un charme!
Shahin Dohan

193

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

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

Pour bootstrap 3, la solution est:

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

Bootstrap 4 a renommé la enforceFocusméthode en _enforceFocus, vous devrez donc le corriger à la place:

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

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

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

Vous pouvez corriger cela rapidement en remplaçant la fonction enforceFocus qui enregistre l'événement sur le modal


1
@pymarco Celui-là aurait dû être là un peu plus tôt pour être choisi comme réponse! Merci mec, d'avoir fourni une vraie réponse à un problème vraiment ennuyeux.
ilter

3
@pymarco C'est la bonne solution. Merci d'avoir économisé mon temps.
VKPRO

2
Vous m'avez fait gagner beaucoup de temps avec un problème qui n'a pas toujours soulevé sa tête. Je vous remercie!
user3036342

1
Cela a fonctionné pour moi !! Je parcourais et parcourais les fils de discussion pour select2 dans github et je n'ai pas rencontré ce message que vous avez fourni. C'était googler et trouver cette page dans stackoverflow ce qui m'a sauvé la vie. Je vous remercie!
luis.ap.uyen

2
où dois-je mettre ce code et quelle fonction doit-il adresser? Désolé, JS noob ici, j'ai essayé d'en faire une partie du select2 JS ou de le placer en haut / fin de page, le tout sans succès. $.fn.modal.Constructor.prototype.enforceFocus = $.noop;
Armitage2k

39

Il suffit de supprimer tabindex="-1"et d'ajouter du styleoverflow:hidden

Voici un exemple:

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

ça marche mais quand j'ai du long modal je ne peux pas faire défiler vers le bas!
Tarek Kalaji

1
@TarekKalaji avez-vous déjà compris comment autoriser le défilement avec cette solution?
OverflowingTheGlass

J'ai essayé de retirer le tabindex mais cela n'a pas été suffisant. Ajouter un débordement: caché est utile si la boîte modale est longue ...
Plasebo

A fonctionné pour moi en supprimant l'attribut d'index d'onglet.
Glen

Juste pour info: la suppression de l'attr tab-index supprimera la possibilité de fermer la fenêtre contextuelle modale par le bouton esc.
curiousBoy

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

Ceci est ma solution avec select2 4.0.0. Remplacez simplement le css juste en dessous de l'importation select2.css. Veuillez vous assurer que le z-index est supérieur à votre boîte de dialogue ou modal. J'ajoute juste 2000 sur ceux par défaut. Parce que le z-index de mes boîtes de dialogue est d'environ 1000.


1
Aucune des solutions n'a fonctionné pour select2 4.0.0 sauf ceci. Merci beaucoup.
Neel

Le même problème se produit si Select2 (v4.0.0) se trouve dans un popover. Dans bootstrap.cssle z-index de .popover1060, ce correctif fonctionne également. Je l'aime parce que c'est simple et qu'il résout le problème de la même manière que le problème a été créé: z-index défini dans une feuille de style.
Paul

2
La solution la plus triviale et pourtant la seule qui a fonctionné. Merci!
Ishtiaque Khan

J'ai ajouté ce qui précède dans mon fichier css, mais il n'a aucun changement. J'utilise jQuery Mobile. Des suggestions s'il vous plait?
Sahil Khanna

@Sahil 1. assurez-vous qu'il a bien remplacé les originaux. le moyen le plus simple est d'ajouter ceci après tous les fichiers css par défaut2. vérifier le z-index, s'assurer qu'il est plus grand que celui de la boîte de dialogue
Diluka W

26

Définissez le menu déroulant Parent. Je devais le mettre sur .modal-content dans le modal ou le texte finirait centré.

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

2
Le .modal-contentfait vraiment une différence. Merci d'avoir signalé 👍
Js Lim

Cela a fonctionné pour moi. Je me demande pourquoi cela n'a pas reçu autant de votes positifs.
chrisbjr

A travaillé pour moi aussi Merci
Neha


9

Selon la documentation officielle select2, ce problème se produit car les modaux Bootstrap ont tendance à voler le focus à d'autres éléments en dehors du modal.

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

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

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

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


Bien. il ne fonctionnait pas avec une magnifique fenêtre contextuelle, maintenant après l'ajout de l'option dropdownParent, cela fonctionne bien.
Yogesh Saroya

8

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

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

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


1
vous devez l'implémenter avec @breq answer pour que cela fonctionne.
Ryan Arief

7

Utilisez ce code sur Document.read ()

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

1
Le nom de fonction approprié est "$ (document) .ready". Le code devrait donc être comme: $ (document) .ready (function () {$ .fn.modal.Constructor.prototype.enforceFocus = function () {};});
Lech Osiński

1
@ LechOsiński - Merci d'avoir décrit comment utiliser ce petit morceau de code. Votre solution est la seule qui a fonctionné pour moi. +1
Francis Bartkowiak

7

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

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

5

changer le fichier select2.css

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

à

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

C'est le seul qui fonctionne pour moi (jquery-ui-1.10.3.css, jquery-ui-1.9.1.js et select2 3.4.0). J'ai 2 dialogues jquery UI l'un sur l'autre et select2 sur le second. J'ai également mis // permettre l'interaction de select2, sélecteur de date et d'heure sur la boîte de dialogue jQuery UI $ .ui.dialog.prototype._allowInteraction = function (e) {return !! $ (e.target) .closest ('. Ui- dialogue, .ui-datepicker, .select2-drop '). length; }; Je n'ai aucune idée si cette aide ou non.
Adrian P.

5

Juste pour mieux comprendre comment les éléments tabindex fonctionnent pour compléter la réponse acceptée:

L'attribut global tabindex est un entier indiquant si l'élément peut prendre le focus d'entrée (est focusable), s'il doit participer à la navigation clavier séquentielle, et si oui, à quelle position. Il peut prendre plusieurs valeurs:
  -une valeur négative signifie que l'élément doit être focalisable, mais ne doit pas être accessible via la navigation séquentielle au clavier;
  -0 signifie que l'élément doit être focalisable et accessible via la navigation séquentielle au clavier, mais son ordre relatif est défini par la convention de plate-forme;
  -un moyen de valeur positive doit être focalisable et accessible via une navigation clavier séquentielle; son ordre relatif est défini par la valeur de l'attribut: le séquentiel suit le nombre croissant du tabindex. Si plusieurs éléments partagent le même index tabulaire, leur ordre relatif suit leur position relative dans le document.

de: Mozilla Devlopper Network


3

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

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
}

Tiré 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' dropdownParentattribut lors de l'initialisation select2:

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

Bonne chance (:


3

Sur la base de 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 select2 et maintient la séquence d'onglets à l'intérieur du 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

Dans mon cas, j'ai eu le même problème avec deux modaux et tout a été résolu en utilisant:

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

Comme dans le numéro 41 du projet, un utilisateur l'a dit.


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

ce code fonctionne. Je vous remercie.


2

D'accord, je sais que je suis en retard à la fête. Mais permettez-moi de 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é conformément aux problèmes courants répertoriés sur le site select2.


1

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


J'utilise jQuery Mobile et j'ai intégré Select2 dans une fenêtre contextuelle. Le code que vous avez fourni fonctionne bien sur un navigateur PC. Mais lorsque j'exécute ce code sur un navigateur mobile, la fenêtre contextuelle se ferme et se rouvre lorsqu'une valeur est sélectionnée. Pouvez-vous suggérer les modifications que je dois apporter?
Sahil Khanna

1

J'ai le même problème avec le select2in bootstrap modal, et la solution était de supprimer le overflow-y: auto;et overflow: hidden; de .modal-openet.modal classes

Voici l'exemple d'utilisation jQuerypour supprimer overflow-y:

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

1

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

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

1

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

J'ai plusieurs modaux avec des formulaires contenant des widgets select2. L'ouverture du modal A, puis d'un autre modal à l'intérieur du modal A, ferait disparaître les widgets select2 à l'intérieur du modal B et ne réussirait pas à s'initialiser.

Chacun de ces modaux chargeait les formulaires via ajax.

La solution consistait à retirer 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
$('.modal').on('shown.bs.modal', function (e) {
    $(this).find('.select2me').select2({
        dropdownParent: $(this).find('.modal-content')
    });
})

1

J'ai résolu cela généralement dans mon projet en surchargeant la select2fonction. Maintenant, il vérifiera s'il n'y a pas de dropdownParent et si la fonction est appelée sur un élément qui a un parent du typediv.modal . Si c'est le cas, il ajoutera ce modal comme parent pour la liste déroulante.

De cette façon, vous n'avez pas à le spécifier chaque fois que vous créez une boîte de sélection2.

(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];
    }
})();

0

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

Essayez iy out

Mon 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

vous pouvez appeler à nouveau le déclencheur select2 dans votre $ (document)

$(".select2").select2({ 
                width: '120' 
            });

0

pour utiliser bootstrap 4.0 côté serveur (ajax ou json data inline), vous devez ajouter tout cela:

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

puis lorsque le modal est ouvert, créez le select2:

  // when modal is open
  $('.modal').on('shown.bs.modal', function () {
            $('select').select2({
                  // ....
            });
  });

-1

Dans mon cas, je l'ai fait et cela fonctionne. J'utilise le bundle pour le charger et dans ce cas cela a fonctionné pour moi

 $(document).on('select2:select', '#Id_Producto', function (evt) {
   // Here your code...
  });
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.