Select2 funktioniert nicht, wenn es in ein Bootstrap-Modal eingebettet ist

337

Wenn ich eine select2 (Eingabe) im Bootstrap-Modal verwende, kann ich nichts eingeben. Es ist wie behindert? Außerhalb des Modals funktioniert select2 einwandfrei.

Geben Sie hier die Bildbeschreibung ein

Arbeitsbeispiel: 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>

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

Antworten:

Hier finden Sie eine schnelle Lösung

und hier ist 'der richtige Weg': Select2 funktioniert nicht, wenn es in ein Bootstrap-Modal eingebettet ist

breq
quelle
1
Das heißt, das Attribut tabindex = "- 1" wird aus dem Element entfernt.
Nikit Barochiya
Die Antwort von dboswell ist die richtige Lösung, ABER das dropdownParentsollte nicht auf dem Root-Div liegen, sondern tiefer, zum Beispiel das Div mit Klasse modal-content, sonst werden die Dropdown-Positionen beim Scrollen des Modals durcheinander gebracht.
Shahin Dohan

Antworten:

605

Ok, ich muss es funktionieren lassen.

Veränderung

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

zu

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

(entferne tabindex = "- 1" aus modal)

breq
quelle
22
Kann es eine andere Lösung geben? Weil das modale Fenster dann nicht mit der Esc-Taste geschlossen wird.
Woto
19
Das Entfernen von tabindex = "- 1" hat bei mir nicht funktioniert. Ich habe gerade <div class = "modal-body"> in <div class = "modal-body" style = "overflow: hidden;"> geändert
Wissem
39
Wie zum Teufel hast du das entdeckt?
DontVoteMeDown
6
Ich habe alle Optionen ausprobiert, aber bei mir funktioniert nichts. Ich benutze select2 4.0
Girish Gupta
7
Vielen Dank! Es ist 4 Jahre her und es ist immer noch eine gültige Lösung.
Linek
247

Für Select2 v4:

Verwenden Sie dropdownParentdiese Option, um das Dropdown-Menü an den modalen Dialog und nicht an den HTML-Text anzuhängen.

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

Dadurch wird das Select2-Dropdown-Menü angehängt, sodass es in das DOM des Modals und nicht in den HTML-Body (Standard) fällt. Siehe https://select2.org/dropdown#dropdown-placement

dboswell
quelle
12
Bestätigt, dies funktioniert wie ein Zauber und scheint die beste Lösung für dieses Problem zu sein!
Lacco
29
Dies funktionierte für mich (mit v4.0.2), aber ich musste es dropdownParent: $("#myModal")nicht verwenden dropdownParent: "#myModal".
Saxon Druce
6
FWIW, in meinem Fall musste ich das dropdownParent auf den Körper des Modals setzen. Durch das Anhängen an das Modal selbst wurde der Z-Index nicht hoch genug angehoben. zB dropdownParent: $ ('. modal-body', '#myModal')
DrewInTheMountains
1
Dies funktioniert einwandfrei, ohne Tabindex zu entfernen. +1
sammry
1
@DrewInTheMountains Ich hatte auch Probleme beim Festlegen der dropdownParentWurzel des Modals. Es ist in der Tat besser, den Körper auszuwählen, da sonst beim Scrollen wirklich schlechte Positionierungsfehler auftreten. Ich setze meine mit Klasse auf die Div modal-contentund es funktioniert wie ein Zauber!
Shahin Dohan
193

Ich habe auf github für select2 eine Lösung dafür gefunden

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

Für Bootstrap 3 lautet die Lösung:

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

Bootstrap 4 hat die enforceFocusMethode in umbenannt _enforceFocus, daher müssen Sie diese stattdessen patchen:

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

Erklärung vom obigen Link kopiert:

Bootstrap registriert einen Listener für das Focusin-Ereignis, der prüft, ob das fokussierte Element entweder das Overlay selbst oder ein Nachkomme davon ist - wenn nicht, konzentriert es sich nur auf das Overlay. Da das Dropdown-Menü select2 an den Text angehängt ist, können Sie effektiv nichts in das Textfeld eingeben.

Sie können dies schnell beheben, indem Sie die Funktion assertceFocus überschreiben, die das Ereignis auf dem Modal registriert

Pymarco
quelle
1
@pymarco Dass man etwas früher dort gewesen sein sollte, um als Antwort ausgewählt zu werden! Danke Mann, dass du eine echte Antwort auf ein wirklich nerviges Problem gegeben hast.
ilter
3
@pymarco Dies ist die richtige Lösung. Danke, dass du mir Zeit gespart hast.
VKPRO
2
Sie haben mir viel Zeit mit einem Problem gespart, das nicht immer den Kopf aufgerichtet hat. Vielen Dank!
user3036342
1
Das hat bei mir funktioniert !! Ich habe die Issues-Threads für select2 in github durchsucht und bin nicht auf den von Ihnen bereitgestellten Beitrag gestoßen. Es war googeln und diese Seite im Stackoverflow zu finden, was mein Leben gerettet hat. Vielen Dank!
luis.ap.uyen
2
Wo lege ich diesen Code ab und welche Funktion sollte er ansprechen? Entschuldigung, JS noob hier, ich habe versucht, dies zu einem Teil des select2 JS zu machen oder es oben / am Ende der Seite zu platzieren, alles ohne Erfolg. $.fn.modal.Constructor.prototype.enforceFocus = $.noop;
Armitage2k
39

Einfach entfernen tabindex="-1"und Stil hinzufügenoverflow:hidden

Hier ist ein Beispiel:

<div id="myModal" class="modal fade" role="dialog" style="overflow:hidden;">
    <!---content modal here -->
</div>
MrBii
quelle
es funktioniert, aber wenn ich lange Modal habe, kann ich nicht nach unten scrollen!
Tarek Kalaji
1
@TarekKalaji Haben Sie jemals herausgefunden, wie Sie mit dieser Lösung das Scrollen zulassen können?
OverflowingTheGlass
Versucht, den Tabindex zu entfernen, war aber nicht genug. Überlauf
hinzufügen
Arbeitete für mich beim Entfernen des Tab-Index-Attributs.
Glen
Nur zu Ihrer Information: Durch Entfernen des Tab-Index-Attributs wird die Möglichkeit zum Schließen des modalen Popups über die Esc-Schaltfläche aufgehoben.
neugierigBoy
31
.select2-close-mask{
    z-index: 2099;
}
.select2-dropdown{
    z-index: 3051;
}

Dies ist meine Lösung mit select2 4.0.0. Überschreiben Sie einfach das CSS direkt unter dem Import von select2.css. Bitte stellen Sie sicher, dass der Z-Index größer ist als Ihr Dialog oder Modal. Ich füge nur 2000 zu den Standard hinzu. Weil der Z-Index meiner Dialoge ungefähr 1000 ist.

Diluka W.
quelle
1
Keine der Lösungen funktionierte für select2 4.0.0, außer dies. Vielen Dank.
Neel
Das gleiche Problem tritt auf, wenn sich Select2 (v4.0.0) in einem Popover befindet. Im bootstrap.cssZ-Index von .popoverist auf 1060 gesetzt, damit dieser Fix auch funktioniert. Ich mag es, weil es einfach ist und das Problem auf die gleiche Weise löst, wie das Problem erstellt wurde: Z-Index in einem Stylesheet.
Paul
2
Die trivialste und doch einzige Lösung, die funktioniert hat. Vielen Dank!
Ishtiaque Khan
Ich habe das oben genannte in meiner CSS-Datei hinzugefügt, aber es hat keine Änderungen. Ich verwende jQuery Mobile. Irgendwelche Vorschläge bitte?
Sahil Khanna
@Sahil 1. Stellen Sie sicher, dass die ursprünglichen erfolgreich überschrieben wurden. Einfacher Weg ist, dies nach all den Standard-CSS-Dateien hinzuzufügen. 2.Überprüfen Sie den Z-Index und stellen Sie sicher, dass er größer als der des Dialogfelds ist
Diluka W
26

Legen Sie das Dropdown-Element fest. Ich musste es auf .modal-content innerhalb des Modals setzen, sonst würde der Text zentriert enden.

$("#product_id").select2({
    dropdownParent: $('#myModal .modal-content')
});
bezz
quelle
2
Das macht .modal-contentwirklich einen Unterschied. Vielen Dank für den Hinweis 👍
Js Lim
Das hat bei mir funktioniert. Ich frage mich, warum dies nicht so viele positive Stimmen bekommen hat.
Chrisbjr
Arbeitete für mich Auch danke
Neha
11

Die Antwort, die für mich funktioniert hat, finden Sie hier: https://github.com/select2/select2-bootstrap-theme/issues/41

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

Auch muss das nicht entfernt werden tabindex.

Ashraf Slamang
quelle
Dies ist der schönste Weg, hält auch alle Funktionen von modal.
Edofre
9

Laut der offiziellen select2-Dokumentation tritt dieses Problem auf, weil Bootstrap-Modale dazu neigen, anderen Elementen außerhalb des Modals den Fokus zu stehlen.

Standardmäßig fügt Select2 das Dropdown-Menü dem Element hinzu und es wird als "außerhalb des Modals" betrachtet.

Fügen Sie stattdessen das Dropdown-Menü mit der Einstellung dropdownParent an das Modal selbst an:

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

Siehe Referenz: https://select2.org/troubleshooter/common-problems

Anas
quelle
Gut. Es funktionierte nicht mit großartigem Popup, jetzt, nachdem die DropdownParent-Option hinzugefügt wurde, funktioniert es einwandfrei.
Yogesh Saroya
8

Ich hatte das gleiche Problem, ein Update z-indexfür .select2-containersollte den Trick machen. z-indexStellen Sie sicher, dass Ihr Modal niedriger ist als das von select2.

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

Aktualisiert: Falls der obige Code nicht richtig funktioniert, entfernen Sie auch tabindexes aus Ihrem Modal, wie von @breq vorgeschlagen

hhk
quelle
1
Sie müssen dies mit der Antwort @breq implementieren, damit es funktioniert.
Ryan Arief
7

Verwenden Sie diesen Code nur in Document.read ()

$.fn.modal.Constructor.prototype.enforceFocus = function () {};
S.Mohamed Mahdi Ahmadian Zadeh
quelle
1
Der richtige Funktionsname lautet "$ (document) .ready". Der Code sollte also wie folgt aussehen: $ (document) .ready (function () {$ .fn.modal.Constructor.prototype.enforceFocus = function () {};});
Lech Osiński
1
@ LechOsiński - Vielen Dank, dass Sie tatsächlich beschrieben haben, wie dieser kleine Codeblock verwendet wird. Ihre Lösung ist die einzige, die für mich funktioniert hat. +1
Francis Bartkowiak
7

Dieses Problem hat sich bei der Arbeit mit der Single Jquery-Funktion gelöst

$('#myModal .select2').each(function() {  
   var $p = $(this).parent(); 
   $(this).select2({  
     dropdownParent: $p  
   });  
});
Vinoth Smart
quelle
Vielen Dank! Dies löste mein Problem
Mihai Alexandru-Ionut
5

Ändern Sie die Datei select2.css

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

zu

z-index: 10000;
...
z-index: 10001;
...
z-index: 10002;
user1616435
quelle
Das ist die einzige, die für mich funktioniert (jquery-ui-1.10.3.css, jquery-ui-1.9.1.js und select2 3.4.0). Ich habe 2 jquery UI-Dialoge übereinander und select2 auf dem zweiten. Außerdem habe ich // die Interaktion von select2, Datums- und Zeitauswahl im jQuery-UI-Dialogfeld $ .ui.dialog.prototype._allowInteraction = function (e) {return !! $ (e.target) .closest ('. Ui- dialog, .ui-datepicker, .select2-drop '). length; }; Ich habe keine Ahnung, ob dies hilft oder nicht.
Adrian P.
5

Nur um besser zu verstehen, wie Tabindex-Elemente funktionieren, um die akzeptierte Antwort zu vervollständigen:

Das globale Attribut tabindex ist eine Ganzzahl, die angibt, ob das Element den Eingabefokus übernehmen kann (fokussierbar ist), ob und an welcher Position es an der sequentiellen Tastaturnavigation teilnehmen soll. Es kann mehrere Werte annehmen:
  - Ein negativer Wert bedeutet, dass das Element fokussierbar sein sollte, aber nicht über die sequentielle Tastaturnavigation erreichbar sein sollte.
  -0 bedeutet, dass das Element über die sequentielle Tastaturnavigation fokussierbar und erreichbar sein sollte, seine relative Reihenfolge jedoch durch die Plattformkonvention definiert ist.
  -Ein Mittel mit positivem Wert sollte über die sequentielle Tastaturnavigation fokussierbar und erreichbar sein. Seine relative Reihenfolge wird durch den Wert des Attributs definiert: Die Folgen folgen der zunehmenden Anzahl des Tabindex. Wenn mehrere Elemente denselben Tabindex verwenden, folgt ihre relative Reihenfolge ihrer relativen Position im Dokument.

von: Mozilla Devlopper Network

538ROMEO
quelle
3

Wenn Sie ein Problem mit dem haben iPad - Tastatur , die sich verstecken , die Bootstrap - modal , während auf dem Klick select2 Eingang, können Sie dies beheben , indem Sie die folgende Regel Zugabe nach der Initialisierung des select2Eingangs:

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
}

Entnommen aus https://github.com/angular-ui/bootstrap/issues/1812#issuecomment-135119475

BEARBEITEN: Wenn Ihre Optionen nicht richtig angezeigt werden, müssen Sie das dropdownParentAttribut beim Initialisieren verwenden select2:

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

Viel Glück (:

Gangai Johann
quelle
3

Basierend auf der Antwort von @pymarco habe ich diese Lösung geschrieben. Sie ist nicht perfekt, löst jedoch das Select2-Fokusproblem und behält die Tab-Sequenz bei, die innerhalb von Modal funktioniert

    $.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))
    }
Angelo Cavalet
quelle
3

In meinem Fall hatte ich das gleiche Problem mit zwei Modalen und alles wurde gelöst mit:

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

Wie in der Projektausgabe Nr. 41 sagte ein Benutzer.

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

Dieser Code funktioniert. Vielen Dank.

Ramazan Polat
quelle
2

Okay, ich weiß, dass ich zu spät zur Party komme. Aber lassen Sie mich mit Ihnen teilen, was für mich funktioniert hat. Die Tabindex- und Z-Index-Lösungen haben bei mir nicht funktioniert.

Das Festlegen des übergeordneten Elements des select-Elements funktionierte gemäß den allgemeinen Problemen, die auf der select2-Site aufgeführt sind.

Joker
quelle
1

Wenn Sie jquery mobile popup verwenden, müssen Sie die Funktion _handleDocumentFocusIn neu schreiben:

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

Dr. Clò Luca
quelle
Ich verwende jQuery Mobile und habe Select2 in ein Popup eingebettet. Der von Ihnen angegebene Code funktioniert gut in einem PC-Browser. Wenn ich diesen Code jedoch in einem mobilen Browser ausführe, wird das Popup geschlossen und wieder geöffnet, wenn ein Wert ausgewählt wird. Können Sie mir Änderungen vorschlagen?
Sahil Khanna
1

Ich habe das gleiche Problem mit dem select2In bootstrap modal, und die Lösung bestand darin, das overflow-y: auto;und zu entfernen overflow: hidden. von .modal-openund.modal classes

Hier ist das Beispiel für die jQueryEntfernung von overflow-y:

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

Ich hatte dieses Problem schon einmal, ich benutze yii2 und ich habe es auf diese Weise gelöst

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

Ich hatte ein halbbezogenes Problem in einer Anwendung, also werde ich mein 2c einfügen.

Ich habe mehrere Modalitäten mit Formularen, die select2-Widgets enthalten. Das Öffnen von Modal A und eines weiteren Modals in Modal A würde dazu führen, dass select2-Widgets in Modal B verschwinden und nicht initialisiert werden können.

Jedes dieser Modalitäten lud die Formulare über Ajax.

Die Lösung bestand darin, die Formulare beim Schließen eines Modals aus dem Dom zu entfernen.

$(document).on('hidden.bs.modal', '.modal', function(e) {
    // make sure we don't leave any select2 widgets around 
    $(this).find('.my-form').remove();
});
Glyphe
quelle
1
$('.modal').on('shown.bs.modal', function (e) {
    $(this).find('.select2me').select2({
        dropdownParent: $(this).find('.modal-content')
    });
})
ocobacho
quelle
1

Ich habe dies allgemein in meinem Projekt gelöst, indem ich die select2-funktion überladen habe . Jetzt wird geprüft, ob kein dropdownParent vorhanden ist und ob die Funktion für ein Element aufgerufen wird, das ein übergeordnetes Element des Typs hat div.modal. In diesem Fall wird dieses Modal als übergeordnetes Element für die Dropdown-Liste hinzugefügt.

Auf diese Weise müssen Sie es nicht jedes Mal angeben, wenn Sie ein select2-Eingabefeld erstellen.

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

Ich bekomme es einfach zum Laufen , indem ich select2.min.css einbinde

Probieren Sie es aus

Mein modales HTML von Bootstrap 3 ist

<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>
Entwickler
quelle
0

Sie können den select2-Trigger in Ihrem $ (Dokument) erneut aufrufen.

$(".select2").select2({ 
                width: '120' 
            });
Sinatrya Yogi Rizal
quelle
0

Um Bootstrap 4.0 serverseitig zu verwenden (Ajax- oder JSON-Daten inline), müssen Sie Folgendes hinzufügen:

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

Wenn dann Modal geöffnet ist, erstellen Sie select2:

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

In meinem Fall habe ich das gemacht und es funktioniert. Ich benutze Bundle, um es zu laden und in diesem Fall hat es für mich funktioniert

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