Select2 nie działa, gdy jest osadzony w modale bootstrap


338

Kiedy używam select2 (input) w modal bootstrap, nie mogę nic w nim wpisać. To jest jak niepełnosprawny? Poza modułem select2 działa dobrze.

wprowadź opis zdjęcia tutaj

Przykład działania: http://jsfiddle.net/byJy8/1/ kod:

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

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

odpowiedzi:

tutaj możesz znaleźć szybką poprawkę

a oto „właściwa droga”: Select2 nie działa, gdy jest osadzony w modale bootstrap


1
Oznacza to usunięcie atrybutu tabindex = "- 1" z elementu.
Nikit Barochiya,

Odpowiedź dboswella jest właściwym rozwiązaniem, ALE, dropdownParentnie powinna ona znajdować się na głównym divie, ale głębiej, na przykład div z klasą modal-content, w przeciwnym razie pozycje rozwijane zostaną pomieszane podczas przewijania modalu.
Shahin Dohan,

Odpowiedzi:


606

Ok, mam to do pracy.

zmiana

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

do

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

(usuń tabindex = "- 1" z modalu)


22
Czy może być inne rozwiązanie? Ponieważ okno modalne nie zamknie się klawiszem Esc.
woto

19
usunięcie tabindex = "- 1" nie działało u mnie. Właśnie zmieniłem <div class = "modal-body"> na <div class = "modal-body" style = "overflow: hidden;">
Wissem,

39
Jak do diabła to odkryłeś?
DontVoteMeDown

6
Wypróbowałem wszystkie opcje, ale nic nie działa dla mnie. Korzystam z select2 4.0
Girish Gupta

7
Dzięki! Minęły 4 lata i wciąż jest to poprawna poprawka.
Linek

248

W przypadku Select2 v4:

Służy dropdownParentdo dołączania menu rozwijanego do modalnego okna dialogowego, a nie do treści 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>

Spowoduje to dołączenie listy rozwijanej Select2, aby mieściła się w DOM modelu modalnego, a nie w treści HTML (domyślnie). Zobacz https://select2.org/dropdown#dropdown-placement


12
Potwierdzono, że działa to jak urok i wydaje się być najlepszym rozwiązaniem tego problemu!
lacco,

29
To działało dla mnie (z wersją 4.0.2), ale musiałem użyć dropdownParent: $("#myModal"), nie dropdownParent: "#myModal".
Saxon Druce

6
FWIW, w moim przypadku musiałem ustawić listę rozwijaną Rodzic do ciała modalu, dołączenie go do samego modalu nie spowodowało dostatecznego podniesienia wskaźnika Z. np. dropdownParent: $ ('. modal-body', '#myModal')
DrewInTheMountains

1
Działa to doskonale bez usuwania tabindex. +1
sammry,

1
@DrewInTheMountains Miałem również problemy z ustawieniem dropdownParentkatalogu głównego modalu, naprawdę lepiej jest wybrać ciało, inaczej dostaniesz naprawdę złe błędy pozycjonowania podczas przewijania. Ustawiłem moje na div z klasą modal-contenti działa jak urok!
Shahin Dohan,

193

Znalazłem rozwiązanie tego na github dla select2

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

W przypadku bootstrap 3 rozwiązaniem jest:

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

Bootstrap 4 zmienił nazwę tej enforceFocusmetody na _enforceFocus, więc zamiast tego musisz załatać:

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

Wyjaśnienie skopiowane z powyższego linku:

Bootstrap rejestruje detektor zdarzenia focusin, który sprawdza, czy elementem skupionym jest sama nakładka, czy jej potomek - jeśli nie, to po prostu zmienia ostrość na nakładce. Z dołączonym do ciała menu select2 skutecznie zapobiega to wprowadzaniu czegokolwiek do pola tekstowego.

Możesz to naprawić, zastępując funkcję enforceFocus, która rejestruje zdarzenie w module


1
@pymarco To powinno być tam trochę wcześniej, aby zostać wybrane jako odpowiedź! Dzięki człowieku, za udzielenie prawdziwej odpowiedzi na naprawdę irytujący problem.
ilter

3
@pymarco To jest prawidłowe rozwiązanie. Dziękuję za oszczędność czasu.
VKPRO,

2
Zaoszczędziłeś mi mnóstwo czasu z problemem, który nie zawsze odwrócił głowę. Dziękuję Ci!
user3036342

1
To zadziałało dla mnie !! Przeglądałem wątki problemów dla select2 w github i nie natknąłem się na ten post, który podałeś. Googlowanie i znajdowanie tej strony w stosie, co uratowało mi życie. Dziękuję Ci!
luis.ap.uyen

2
gdzie mam umieścić ten kod i do jakiej funkcji powinien on adresować? Niestety, JS noob tutaj, próbowałem uczynić to częścią select2 JS lub umieszczając go na górze / końcu strony, wszystko bez powodzenia. $.fn.modal.Constructor.prototype.enforceFocus = $.noop;
Armitage2k,

39

Po prostu usuń tabindex="-1"i dodaj styloverflow:hidden

Oto przykład:

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

to działa, ale kiedy mam długi modal, nie mogę przewijać w dół!
Tarek Kalaji,

1
@TarekKalaji, czy kiedykolwiek zastanawiałeś się, jak zezwolić na przewijanie za pomocą tego rozwiązania?
Przepełnienie

Próbowałem usunąć tabindex, ale nie wystarczyło. Dodanie przelewu: ukryty przydaje się, jeśli pudełko modalne jest długie ...
Plasebo,

Pracowało dla mnie usunięcie atrybutu indeksu tabulatorów.
Glen

Po prostu FYI: usunięcie atrybutu tab-index attr usunie możliwość zamykania modalnego wyskakującego przycisku Esc.
curiousBoy

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

To jest moje rozwiązanie z select2 4.0.0. Wystarczy zastąpić css bezpośrednio poniżej importu select2.css. Upewnij się, że indeks Z jest większy niż twoje okno dialogowe lub modalne. Właśnie dodam 2000 do domyślnych. Ponieważ indeks Z moich okien dialogowych wynosi około 1000.


1
Żadne z rozwiązań nie działało dla select2 4.0.0, z wyjątkiem tego. Wielkie dzięki.
Neel

Ten sam problem występuje, jeśli Select2 (v4.0.0) jest w oknie popover. W bootstrap.cssindeksie Z .popoverustawiono wartość 1060, więc ta poprawka również działa. Podoba mi się, ponieważ jest prosty i rozwiązuje problem w taki sam sposób, w jaki problem został utworzony: indeks Z ustawiony w arkuszu stylów.
Paul

2
Najbardziej trywialne, ale jedyne rozwiązanie, które działało. Dzięki!
Ishtiaque Khan

Dodałem powyższe w moim pliku css, ale nie ma żadnych zmian. Korzystam z jQuery Mobile. Wszelkie sugestie proszę?
Sahil Khanna

@ Sahil 1. upewnij się, że udało się zastąpić oryginalne. prostym sposobem jest dodanie tego po wszystkich domyślnych plikach css2. zaznacz indeks z, upewnij się, że jest większy niż okno dialogowe
Diluka W

26

Ustaw dropdownParent. Musiałem ustawić go na .modal-content w modalu, inaczej tekst skończyłby się na środku.

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

2
To .modal-contentnaprawdę robi różnicę. Dzięki za wskazanie 👍
Js Lim

To zadziałało dla mnie. Zastanawiam się, dlaczego nie uzyskało tylu głosów pozytywnych.
chrisbjr

Pracował dla mnie również dzięki
Neha


9

Według oficjalnej dokumentacji select2 ten problem występuje, ponieważ moduły Bootstrap mają tendencję do kradzieży fokusu z innych elementów poza modalem.

Domyślnie Select2 dołącza menu rozwijane do elementu i jest uważane za „poza modalne”.

Zamiast tego dołącz menu rozwijane do samego modalu za pomocą ustawienia dropdownParent:

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

Patrz odniesienie: https://select2.org/trou Rozwiązywanie problemów / common-problems


Dobrze. nie działało ze wspaniałym wyskakującym oknem, teraz po dodaniu opcji dropdownParent działa dobrze.
Yogesh Saroya,

8

Miałem ten sam problem, aktualizując z-indexna .select2-containerpowinno załatwić sprawę. Upewnij się, że twój modal z-indexjest niższy niż select2.

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

Zaktualizowano: Jeśli powyższy kod nie działa poprawnie, usuń tabindexy z modalu, jak sugerował @breq


1
musisz to zaimplementować z odpowiedzią @breq, aby działało.
Ryan Arief,

7

Po prostu użyj tego kodu w Document.read ()

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

1
Prawidłowa nazwa funkcji to „$ (dokument) .ready”. Zatem kod powinien wyglądać następująco: $ (dokument) .ready (function () {$ .fn.modal.Constructor.prototype.enforceFocus = function () {};});
Lech Osiński

1
@ LechOsiński - Dziękujemy za opisanie, jak korzystać z tego małego fragmentu kodu. Twoje rozwiązanie jest jedynym, które działało dla mnie. +1
Francis Bartkowiak

7

Ten problem został rozwiązany Funkcja Single Jquery dla mnie działa

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

5

zmień plik select2.css

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

do

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

Tylko to działa dla mnie (jquery-ui-1.10.3.css, jquery-ui-1.9.1.js i select2 3.4.0). Mam 2 okna dialogowe interfejsu użytkownika jquery, jeden na drugim, i wybieram 2 na drugim. Również umieściłem // zezwalam na interakcję selektora select2, daty i godziny w oknie dialogowym interfejsu użytkownika jQuery $ .ui.dialog.prototype._allowInteraction = function (e) {return !! $ (e.target) .closest ('. Ui- dialog, .ui-datepicker, .select2-drop '). length; }; Nie mam pojęcia, czy to pomoże, czy nie.
Adrian P.

5

Aby lepiej zrozumieć, jak działają elementy tabindex, aby wypełnić zaakceptowaną odpowiedź:

Globalny atrybut tabindex jest liczbą całkowitą wskazującą, czy element może przyjmować fokus wejściowy (jest fokowalny), czy powinien uczestniczyć w sekwencyjnej nawigacji po klawiaturze, a jeśli tak, to w jakiej pozycji. Może przyjmować kilka wartości:
  - wartość ujemna oznacza, że ​​element powinien być ustawiany, ale nie powinien być osiągalny poprzez sekwencyjną nawigację za pomocą klawiatury;
  -0 oznacza, że ​​element powinien być nastawialny i osiągalny poprzez sekwencyjną nawigację za pomocą klawiatury, ale jego względna kolejność jest określona przez konwencję platformy;
  -środki o wartości dodatniej powinny być nastawialne i osiągalne poprzez sekwencyjną nawigację za pomocą klawiatury; jego względna kolejność jest zdefiniowana przez wartość atrybutu: sekwencyjne podążają za rosnącą liczbą tabindex. Jeśli kilka elementów ma ten sam tabindex, ich względna kolejność jest zgodna z ich względną pozycją w dokumencie.

od: Mozilla Devlopper Network


3

Jeśli masz problem z iPad klawiaturze, która ukrywa się modal bootstrap podczas klikania na select2 wejścia, można rozwiązać ten problem, dodając następującą regułę po inicjalizacji select2wejścia:

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
}

Zaczerpnięte z https://github.com/angular-ui/bootstrap/issues/1812#issuecomment-135119475

EDYCJA: Jeśli opcje nie są wyświetlane poprawnie, musisz użyć dropdownParentatrybutu podczas inicjowania select2:

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

Powodzenia (:


3

Na podstawie odpowiedzi @pymarco, którą napisałem, to rozwiązanie nie jest idealne, ale rozwiązuje problem focus2 i utrzymuje sekwencję tabulatorów wewnątrz modalnego

    $.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

W moim przypadku miałem ten sam problem z dwoma modułami i wszystko zostało rozwiązane za pomocą:

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

Podobnie jak w numerze 41 projektu, powiedział użytkownik.


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

ten kod działa. Dziękuję Ci.


2

Okej, wiem, że jestem spóźniony na przyjęcie. Ale pozwól, że podzielę się z Tobą tym, co dla mnie zadziałało. Rozwiązania tabindex i z-index nie działały dla mnie.

Ustawienie elementu nadrzędnego elementu select działało zgodnie z typowymi problemami wymienionymi na stronie select2.


1

Jeśli używasz mobilnego wyskakującego okienka jquery, musisz przepisać funkcję _handleDocumentFocusIn:

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


Używam jQuery Mobile i osadziłem Select2 w wyskakującym okienku. Podany kod działa dobrze w przeglądarce komputera. Ale kiedy uruchamiam ten kod w przeglądarce mobilnej, wyskakujące okno zamyka się i otwiera ponownie po wybraniu dowolnej wartości. Czy możesz zasugerować jakieś zmiany, które muszę wprowadzić?
Sahil Khanna

1

Że ten sam problem z select2IN bootstrap modal, i roztwór w celu usunięcia overflow-y: auto;i overflow: hidden; z .modal-openi.modal classes

Oto przykład użycia jQuerydo usunięcia overflow-y:

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

1

miałem ten problem wcześniej, używam yii2 i rozwiązałem go w ten sposób

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

1

Miałem częściowo związany problem w aplikacji, więc wstawię 2c.

Mam wiele modów z formularzami zawierającymi widżety select2. Otwarcie modułu A, a następnie innego modułu w module A, spowodowałoby zniknięcie widżetów select2 w module B i nie zainicjowanie.

Każdy z tych modułów ładował formularze za pośrednictwem ajax.

Rozwiązaniem było usunięcie formularzy z domku podczas zamykania modalu.

$(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

Rozwiązałem to ogólnie w moim projekcie, przeciążając select2funkcję-. Teraz sprawdzi, czy nie ma dropdownParent i czy funkcja jest wywoływana na elemencie, który ma rodzica typu div.modal. Jeśli tak, doda ten modal jako element nadrzędny menu rozwijanego.

W ten sposób nie musisz go określać za każdym razem, gdy tworzysz pole select2-input.

(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

Po prostu zaczynam działać, włączając select2.min.css

Wypróbuj

Mój modalny HTML Bootstrap 3 to

<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

aby użyć bootstrap 4.0 po stronie serwera (wbudowane dane ajax lub json), musisz dodać to wszystko:

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

a następnie, gdy modal jest otwarty, utwórz select2:

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

-1

W moim przypadku to zrobiłem i działa. Używam pakietu, aby go załadować iw tym przypadku zadziałało to dla mnie

 $(document).on('select2:select', '#Id_Producto', function (evt) {
   // Here your code...
  });
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.