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.