Select2 non funziona se incorporato in un modale bootstrap


338

Quando uso un select2 (input) in modal bootstrap, non riesco a digitare nulla al suo interno. È come disabilitato? Al di fuori del modale select2 funziona bene.

inserisci qui la descrizione dell'immagine

Esempio di lavoro: http://jsfiddle.net/byJy8/1/ codice:

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

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

risposte:

qui puoi trovare una soluzione rapida

e qui è "la strada giusta": Select2 non funziona se incorporato in un bootstrap modale


1
Cioè, rimuovendo l'attributo tabindex = "- 1" dall'elemento.
Nikit Barochiya,

La risposta di dboswell è la soluzione giusta, MA dropdownParentnon dovrebbe essere sul div radice, ma più in profondità, ad esempio il div con classe modal-content, altrimenti le posizioni a discesa vengono incasinate quando si scorre il modale.
Shahin Dohan,

Risposte:


606

Ok, ho funzionato.

modificare

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

per

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

(rimuovi tabindex = "- 1" dal modale)


22
Potrebbe esserci un'altra soluzione? Perché la finestra modale non si chiuderà con il tasto Esc.
woto,

19
rimuovendo tabindex = "- 1" non ha funzionato da me. Ho appena cambiato <div class = "modal-body"> in <div class = "modal-body" style = "overflow: hidden;">
Wissem,

39
Come diavolo l'hai scoperto?
DontVoteMeDown,

6
Ho provato tutte le opzioni, ma niente funziona per me. Sto usando select2 4.0
Girish Gupta

7
Grazie! Sono passati 4 anni ed è ancora una soluzione valida.
Linek,

248

Per Select2 v4:

Utilizzare dropdownParentper collegare il menu a discesa alla finestra di dialogo modale, anziché al corpo 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>

Ciò collegherà il menu a discesa Select2 in modo che rientri nel DOM del modale anziché nel corpo HTML (impostazione predefinita). Vedi https://select2.org/dropdown#dropdown-placement


12
Confermato, funziona come un incantesimo e sembra essere la migliore soluzione a questo problema!
Lacco,

29
Questo ha funzionato per me (con v4.0.2), ma ho dovuto usare dropdownParent: $("#myModal"), non è dropdownParent: "#myModal".
Saxon Druce,

6
FWIW, nel mio caso avevo bisogno di impostare il dropdownParent sul corpo del modale, collegandolo al modale stesso non ha portato l'indice z abbastanza in alto. ad esempio dropdownParent: $ ('. modal-body', '#myModal')
DrewInTheMountains

1
Funziona perfettamente senza rimuovere tabindex. +1
sammry,

1
@DrewInTheMountains Ho anche avuto problemi a impostare la dropdownParentradice del modale, è davvero meglio scegliere il corpo, altrimenti si ottengono davvero cattivi bug di posizionamento durante lo scorrimento. Ho impostato il mio sul div con classe modal-contente funziona come un fascino!
Shahin Dohan,

193

Ho trovato una soluzione a questo su github per select2

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

Per bootstrap 3, la soluzione è:

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

Bootstrap 4 ha rinominato il enforceFocusmetodo in _enforceFocus, quindi dovrai invece patcharlo:

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

Spiegazione copiata dal link sopra:

Bootstrap registra un ascoltatore nell'evento focusin che controlla se l'elemento focalizzato è o l'overlay stesso o un suo discendente - se non semplicemente si focalizza nuovamente sull'overlay. Con il menu a discesa select2 attaccato al corpo, ciò ti impedisce effettivamente di inserire qualsiasi cosa nel campo di testo.

È possibile correggere questo problema sovrascrivendo la funzione enforceFocus che registra l'evento sul modale


1
@pymarco Quello dovrebbe essere stato lì un po 'prima per essere scelto come risposta! Grazie amico, per aver fornito una risposta reale a un problema davvero fastidioso.
ilter

3
@pymarco Questa è la soluzione corretta. Grazie per avermi risparmiato tempo.
VKPRO,

2
Mi hai risparmiato un sacco di tempo con un problema che non sempre ha sollevato la testa. Grazie!
user3036342,

1
Questo ha funzionato per me !! Stavo navigando e sfogliando i thread dei problemi per select2 in github e non ho incontrato il post che hai fornito. È stato googling e trovare questa pagina in StackOverflow ciò che mi ha salvato la vita. Grazie!
luis.ap.uyen,

2
dove metto questo codice e quale funzione dovrebbe rivolgersi? Siamo spiacenti, JS Noob qui, ho provato a renderlo parte del JS select2 o posizionandolo nella parte superiore / finale della pagina, il tutto senza successo. $.fn.modal.Constructor.prototype.enforceFocus = $.noop;
Armitage2k,

39

Basta rimuovere tabindex="-1"e aggiungere stileoverflow:hidden

Ecco un esempio:

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

funziona ma quando ho un modale lungo non riesco a scorrere verso il basso!
Tarek Kalaji,

1
@TarekKalaji hai mai capito come consentire lo scorrimento con questa soluzione?
OverflowingTheGlass

Ho provato a rimuovere il tabindex ma non era abbastanza. Aggiunta di overflow: nascosto è utile se la casella modale è lunga ...
Plasebo

Ha funzionato per me rimuovendo l'attributo dell'indice di tabulazione.
Glen,

Cordiali saluti: la rimozione di tab-index attr rimuoverà la possibilità di chiudere il popup modale tramite il pulsante esc.
curiousBoy,

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

Questa è la mia soluzione con select2 4.0.0. Basta sovrascrivere i CSS proprio sotto l'importazione select2.css. Assicurati che l'indice z sia maggiore della finestra di dialogo o modale. Ho appena aggiunto 2000 a quelli predefiniti. Perché l'indice z dei miei dialoghi è circa 1000.


1
Nessuna delle soluzioni ha funzionato per select2 4.0.0 tranne questo. Molte grazie.
Neel,

Lo stesso problema si verifica se Select2 (v4.0.0) è in un popover. Nell'indice bootstrap.cssz di .popoverè impostato su 1060, quindi anche questa correzione funziona. Mi piace perché è semplice e risolve il problema nello stesso modo in cui è stato creato il problema: z-index impostato in un foglio di stile.
Paul

2
La soluzione più banale eppure l'unica che ha funzionato. Grazie!
Ishtiaque Khan,

Ho aggiunto quanto sopra nel mio file CSS, ma non ha modifiche. Sto usando jQuery Mobile. Qualche suggerimento per favore?
Sahil Khanna,

@Sahil 1. assicurati che abbia superato con successo quelli originali. modo semplice è aggiungere questo dopo tutti i file css predefiniti2. Controllare l'indice z, assicurarsi che sia più grande della finestra di dialogo
Diluka W

26

Imposta il menu a discesa. Ho dovuto impostarlo su .modal-content all'interno del modale o il testo sarebbe stato centrato.

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

2
Fa .modal-contentdavvero la differenza. Grazie per aver sottolineato 👍
Js Lim,

Questo ha funzionato per me. Mi chiedo perché questo non abbia ottenuto tanti voti positivi.
chrisbjr,

Ha funzionato anche per me Grazie
Neha il


9

Secondo la documentazione ufficiale di select2 questo problema si verifica perché i modali Bootstrap tendono a rubare l'attenzione da altri elementi al di fuori del modale.

Per impostazione predefinita, Select2 collega il menu a discesa all'elemento ed è considerato "esterno al modale".

Collega invece il menu a discesa al modale stesso con l'impostazione dropdownParent:

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

Vedi riferimento: https://select2.org/troubleshooter/common-problems


Buona. non funzionava con il magnifico popup, ora dopo aver aggiunto l'opzione dropdownParent funziona bene.
Yogesh Saroya,

8

Ho avuto lo stesso problema, l'aggiornamento z-indexper .select2-containerdovrebbe fare il trucco. Assicurati che i tuoi modali z-indexsiano inferiori a quelli di select2.

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

Aggiornato: se il codice sopra non funziona correttamente, rimuovi anche i tabindex dal tuo modale come suggerito da @breq


1
è necessario implementarlo con la risposta di @breq per farlo funzionare.
Ryan Arief,

7

Jus usa questo codice su Document.read ()

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

1
Il nome della funzione corretta è "$ (documento) .ready". Quindi il codice dovrebbe essere come: $ (document) .ready (function () {$ .fn.modal.Constructor.prototype.enforceFocus = function () {};});
Lech Osiński,

1
@ LechOsiński - Grazie per aver effettivamente descritto come utilizzare questo piccolo pezzo di codice. La tua soluzione è l'unica che ha funzionato per me. +1
Francis Bartkowiak,

7

Questo problema ha funzionato per me Funzione jquery singola

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

5

cambia il file select2.css

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

per

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

Questo è l'unico che funziona per me (jquery-ui-1.10.3.css, jquery-ui-1.9.1.js e select2 3.4.0). Ho 2 finestre di dialogo dell'interfaccia utente jquery una sopra l'altra e seleziona2 sulla seconda. Inoltre ho inserito // consenti l'interazione di select2, selettore data e ora nella finestra di dialogo dell'interfaccia utente jQuery $ .ui.dialog.prototype._allowInteraction = function (e) {return !! $ (e.target) .closest ('. Ui- dialog, .ui-datepicker, .select2-drop '). lunghezza; }; Non ho idea se questo aiuto o no.
Adrian P.

5

Giusto per capire meglio come funzionano gli elementi tabindex per completare la risposta accettata:

L'attributo globale tabindex è un numero intero che indica se l'elemento può prendere il focus di input (è focusable), se dovrebbe partecipare alla navigazione sequenziale della tastiera e, in tal caso, in quale posizione. Può assumere diversi valori:
  -un valore negativo significa che l'elemento dovrebbe essere focalizzabile, ma non dovrebbe essere raggiungibile tramite la navigazione sequenziale della tastiera;
  -0 significa che l'elemento dovrebbe essere focalizzabile e raggiungibile tramite la navigazione sequenziale della tastiera, ma il suo ordine relativo è definito dalla convenzione della piattaforma;
  -un mezzo di valore positivo dovrebbe essere focalizzabile e raggiungibile tramite la navigazione sequenziale della tastiera; il suo ordine relativo è definito dal valore dell'attributo: il sequenziale segue il numero crescente del tabindex. Se più elementi condividono lo stesso tabindex, il loro ordine relativo segue la loro posizione relativa nel documento.

da: Mozilla Devlopper Network


3

Se hai un problema con la tastiera dell'iPad che nasconde il bootstrap modale mentre fai clic sull'ingresso select2 , puoi risolverlo aggiungendo la seguente regola dopo l'inizializzazione select2dell'input:

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
}

Tratto da https://github.com/angular-ui/bootstrap/issues/1812#issuecomment-135119475

MODIFICA: se le opzioni non sono visualizzate correttamente, è necessario utilizzare l' dropdownParentattributo durante l'inizializzazione select2:

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

In bocca al lupo (:


3

Basato sulla risposta di @pymarco, ho scritto questa soluzione, non è perfetta, ma risolve il problema di focus select2 e mantiene la sequenza delle schede funzionante all'interno del modale

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

Nel mio caso ho avuto lo stesso problema con due modali e tutto è stato risolto usando:

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

Come nel numero 41 del progetto , ha detto un utente.


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

questo codice funziona. Grazie.


2

Ok, so che sono in ritardo alla festa. Ma lasciami condividere con te ciò che ha funzionato per me. Le soluzioni tabindex e z-index non hanno funzionato per me.

L'impostazione del genitore dell'elemento select ha funzionato secondo i problemi comuni elencati nel sito select2.


1

Se usi il popup mobile jquery devi riscrivere la funzione _handleDocumentFocusIn:

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


Sto usando jQuery Mobile e ho incorporato Select2 in un popup. Il codice che hai fornito funziona bene su un browser per PC. Ma quando eseguo questo codice su un browser mobile, il popup si chiude e si riapre quando viene selezionato un valore. Puoi suggerire eventuali modifiche che devo apportare?
Sahil Khanna,

1

Ho lo stesso problema con select2in bootstrap modale la soluzione era rimuovere overflow-y: auto;e overflow: hidden; da .modal-opene.modal classes

Ecco l'esempio dell'utilizzo jQueryper rimuovere overflow-y:

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

1

ho avuto questo problema prima, sto usando yii2 e l'ho risolto in questo modo

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

1

Ho avuto un problema semi-correlato in un'applicazione, quindi inserirò il mio 2c.

Ho più modali con moduli contenenti widget select2. L'apertura del modale A, quindi di un altro modale all'interno del modale A, causerebbe la scomparsa dei widget select2 all'interno del modale B e l'inizializzazione.

Ognuna di queste modali stava caricando i moduli tramite Ajax.

La soluzione era rimuovere i moduli dal dom quando si chiudeva un modale.

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

Ho risolto questo problema nel mio progetto sovraccaricando la funzione select2. Ora controllerà se non c'è dropdownParent e se la funzione viene chiamata su un elemento che ha un genitore del tipo div.modal. In tal caso, aggiungerà quel modale come genitore per il menu a discesa.

In questo modo, non è necessario specificarlo ogni volta che si crea un box di input2.

(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

Ho appena funzionato includendo select2.min.css

Prova

Il mio HTML modale di bootstrap 3 è

<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

puoi chiamare nuovamente il trigger select2 nel tuo $ (documento)

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

0

per utilizzare bootstrap 4.0 con lato server (dati ajax o json in linea), è necessario aggiungere tutto questo:

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

e quindi quando modale è aperto, crea select2:

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

-1

Nel mio caso l'ho fatto e funziona. Uso il bundle per caricarlo e in questo caso ha funzionato per me

 $(document).on('select2:select', '#Id_Producto', function (evt) {
   // Here your code...
  });
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.