Select2 no funciona cuando está incrustado en un modo de arranque


338

Cuando uso un select2 (input) en el modo de arranque, no puedo escribir nada en él. Es como deshabilitado? Fuera del modal select2 funciona bien.

ingrese la descripción de la imagen aquí

Ejemplo de trabajo: 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>

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

respuestas:

aquí puedes encontrar una solución rápida

y aquí está "la forma correcta": Select2 no funciona cuando está incrustado en un modo de arranque


1
Es decir, eliminar el atributo tabindex = "- 1" del elemento.
Nikit Barochiya

La respuesta de dboswell es la solución correcta, PERO, dropdownParentno debería estar en el div raíz, sino más profundo, por ejemplo, el div con clase modal-content, de lo contrario, las posiciones desplegables se confunden al desplazar el modal.
Shahin Dohan el

Respuestas:


606

Ok, lo tengo para trabajar.

cambio

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

a

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

(eliminar tabindex = "- 1" de modal)


22
Puede haber otra solución? Porque la ventana modal no se cerrará con la tecla Esc.
woto

19
eliminar tabindex = "- 1" no funcionó de mí. Acabo de cambiar <div class = "modal-body"> a <div class = "modal-body" style = "overflow: hidden;">
Wissem

39
¿Cómo demonios descubriste eso?
DontVoteMeDown

66
He probado todas las opciones, pero nada funciona para mí. Estoy usando select2 4.0
Girish Gupta

77
¡Gracias! Han pasado 4 años y sigue siendo una solución válida.
Linek

248

Para Select2 v4:

Use dropdownParentpara adjuntar el menú desplegable al cuadro de diálogo modal, en lugar del cuerpo 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>

Esto adjuntará el menú desplegable Select2 para que caiga dentro del DOM del modal en lugar del cuerpo HTML (el valor predeterminado). Ver https://select2.org/dropdown#dropdown-placement


12
Confirmado, ¡esto funciona a las mil maravillas y parece ser la mejor solución para este problema!
lacco

29
Esto funcionó para mí (con v4.0.2), pero tuve que usar dropdownParent: $("#myModal"), no dropdownParent: "#myModal".
Saxon Druce

66
FWIW, en mi caso, necesitaba establecer el menú desplegable Padres en el cuerpo del modal, adjuntarlo al modal en sí mismo no elevó el índice z lo suficientemente alto. Por ejemplo, dropdownParent: $ ('. modal-body', '#myModal')
DrewInTheMountains

1
Esto funciona perfectamente bien sin eliminar tabindex. +1
sammry

1
@DrewInTheMountains También tuve problemas para configurar la dropdownParentraíz del modal, de hecho, es mejor elegir el cuerpo, de lo contrario, obtendrá errores de posicionamiento realmente malos al desplazarse. ¡Puse el mío en el div con clase modal-contenty funciona de maravilla!
Shahin Dohan el

193

Encontré una solución a esto en github para select2

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

Para bootstrap 3, la solución es:

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

Bootstrap 4 renombró el enforceFocusmétodo a _enforceFocus, por lo que deberá parchear eso en su lugar:

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

Explicación copiada del enlace de arriba:

Bootstrap registra un oyente para el evento focusin que verifica si el elemento enfocado es la superposición en sí o un descendiente del mismo; de lo contrario, solo se vuelve a enfocar en la superposición. Con el menú desplegable select2 adjunto al cuerpo, esto evita que ingrese cualquier cosa en el campo de texto.

Puede corregir esto rápidamente sobrescribiendo la función enforceFocus que registra el evento en el modal


1
@pymarco ¡Ese debería haber estado allí un poco antes para ser elegido como la respuesta! Gracias hombre, por dar una respuesta real a un problema realmente molesto.
ilter

3
@pymarco Esta es la solución correcta. Gracias por salvarme el tiempo.
VKPRO

2
Me ahorraste un montón de tiempo con un problema que no siempre fue posterior. ¡Gracias!
user3036342

1
¡Esto funcionó para mí! Estaba navegando y navegando por los hilos de problemas para select2 en github y no me encontré con esa publicación que proporcionaste. Fue buscar en Google y encontrar esta página en stackoverflow lo que me salvó la vida. ¡Gracias!
luis.ap.uyen

2
¿Dónde pongo este código y qué función debería abordar? Lo siento, novato de JS aquí, intenté hacer esto parte de J2 select2 o colocarlo en la parte superior / final de la página, todo sin éxito. $.fn.modal.Constructor.prototype.enforceFocus = $.noop;
Armitage2k

39

Simplemente elimine tabindex="-1"y agregue estilooverflow:hidden

Aquí hay un ejemplo:

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

funciona, pero cuando tengo modal largo no puedo desplazarme hacia abajo.
Tarek Kalaji

1
@TarekKalaji, ¿alguna vez descubriste cómo permitir el desplazamiento con esta solución?
OverflowingTheGlass

Intenté eliminar el tabindex pero no fue suficiente. Agregar desbordamiento: oculto es útil si el cuadro modal es largo ...
Plasebo 02 de

Me funcionó eliminando el atributo de índice de pestaña.
Glen

Solo para su información: la eliminación de tab-index attr eliminará la posibilidad de cerrar la ventana emergente modal con el botón esc.
curiousBoy

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

Esta es mi solución con select2 4.0.0. Simplemente anule el CSS justo debajo de la importación select2.css. Asegúrese de que el índice z sea mayor que su diálogo o modal. Acabo de agregar 2000 en los predeterminados. Porque el índice z de mis cuadros de diálogo es de aproximadamente 1000.


1
Ninguna de las soluciones funcionó para select2 4.0.0, excepto esto. Muchas gracias.
Neel

El mismo problema ocurre si Select2 (v4.0.0) está en una ventana emergente. En bootstrap.cssel índice z de .popoverse establece en 1060, por lo que esta solución también funciona. Me gusta porque es simple y resuelve el problema de la misma manera que se creó: el índice z establecido en una hoja de estilo.
Paul

2
La más trivial pero la única solución que funcionó. ¡Gracias!
Ishtiaque Khan

He agregado lo anterior en mi archivo css, pero no tiene cambios. Estoy usando jQuery Mobile. ¿Alguna sugerencia por favor?
Sahil Khanna

@Sahil 1. asegúrese de que haya anulado con éxito los originales. Una forma simple es agregar esto después de todos los archivos css predeterminados2. verifique el índice z, asegúrese de que sea más grande que el diálogo
Diluka W

26

Establecer el menú desplegable Tuve que configurarlo en .modal-content dentro del modal o el texto terminaría centrado.

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

2
El .modal-contentrealmente hacer una diferencia. Gracias por señalar 👍
Js Lim

Esto funcionó para mí. Me pregunto por qué esto no recibió tantos votos positivos.
chrisbjr

Trabajó para mí También gracias
Neha


9

Según la documentación oficial de select2, este problema se produce porque los modales de Bootstrap tienden a robar el foco de otros elementos fuera del modal.

Por defecto, Select2 adjunta el menú desplegable al elemento y se considera "fuera del modal".

En su lugar, adjunte el menú desplegable al modal en sí con la configuración desplegable Padres:

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

Ver referencia: https://select2.org/troubleshooting/common-problems


Bueno. no funcionaba con una ventana emergente magnífica, ahora después de agregar la opción desplegable, el padre funciona bien.
Yogesh Saroya

8

Tuve el mismo problema, actualizar z-indexpara .select2-containerdebería hacer el truco. Asegúrese de que su modal z-indexsea ​​más bajo que select2.

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

Actualizado: en caso de que el código anterior no funcione correctamente, también elimine los índices de tabulación de su modal como sugirió @breq


1
necesita implementar esto con la respuesta @breq para que funcione.
Ryan Arief

7

Simplemente use este código en Document.read ()

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

1
El nombre de la función adecuada es "$ (documento) .ready". Entonces el código debería ser como: $ (document) .ready (function () {$ .fn.modal.Constructor.prototype.enforceFocus = function () {};});
Lech Osiński el

1
@ LechOsiński - Gracias por describir cómo utilizar este pequeño fragmento de código. Su solución es la única que funcionó para mí. +1
Francis Bartkowiak

7

Este problema no funcionaba para mí Función Jquery simple

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

5

cambiar el archivo select2.css

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

a

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

Ese es el único que funciona para mí (jquery-ui-1.10.3.css, jquery-ui-1.9.1.js y select2 3.4.0). Tengo 2 diálogos de interfaz de usuario jquery uno encima del otro y select2 en el segundo. También he puesto // permitir la interacción de select2, selector de fecha y hora en el diálogo de la interfaz de usuario jQuery $ .ui.dialog.prototype._allowInteraction = function (e) {return !! $ (e.target) .closest ('. Ui- cuadro de diálogo, .ui-datepicker, .select2-drop '). length; }; No tengo idea si esto ayuda o no.
Adrian P.

5

Solo para comprender mejor cómo funcionan los elementos tabindex para completar la respuesta aceptada:

El atributo global tabindex es un número entero que indica si el elemento puede tomar el foco de entrada (es enfocable), si debería participar en la navegación secuencial del teclado y, de ser así, en qué posición. Puede tomar varios valores:
  -un valor negativo significa que el elemento debe ser enfocable, pero no debe ser accesible a través de la navegación secuencial del teclado;
  -0 significa que el elemento debe ser enfocable y accesible a través de la navegación secuencial del teclado, pero su orden relativo está definido por la convención de la plataforma;
  -un medio de valor positivo debe ser enfocable y accesible a través de la navegación secuencial del teclado; su orden relativo se define por el valor del atributo: el secuencial sigue el número creciente del índice de tabulación. Si varios elementos comparten el mismo índice de tabulación, su orden relativo sigue su posición relativa en el documento.

de: Red Mozilla Devlopper


3

Si tiene un problema con el teclado del iPad que oculta el modo de arranque al hacer clic en la entrada select2 , puede resolver esto agregando la siguiente regla después de la inicialización de la select2entrada:

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
}

Tomado de https://github.com/angular-ui/bootstrap/issues/1812#issuecomment-135119475

EDITAR: si sus opciones no se muestran correctamente, debe usar el dropdownParentatributo al inicializar select2:

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

Buena suerte (:


3

Basado en la respuesta de @pymarco, escribí esta solución, no es perfecta, pero resuelve el problema de enfoque select2 y mantiene la secuencia de pestañas trabajando dentro del 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

En mi caso tuve el mismo problema con dos modales y todo se resolvió usando:

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

Como en el problema del proyecto # 41, dijo un usuario.


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

Este código está funcionando. Gracias.


2

Bien, sé que llego tarde a la fiesta. Pero déjame compartir contigo lo que funcionó para mí. Las soluciones tabindex y z-index no me funcionaron.

La configuración del elemento primario del elemento select funcionó según los problemas comunes enumerados en el sitio select2.


1

Si usa jquery mobile popup, debe reescribir la función _handleDocumentFocusIn:

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


Estoy usando jQuery Mobile y he incorporado Select2 en una ventana emergente. El código que ha proporcionado funciona bien en un navegador de PC. Pero cuando ejecuto este código en un navegador móvil, la ventana emergente se cierra y se vuelve a abrir cuando se selecciona cualquier valor. ¿Me puede sugerir algún cambio que deba hacer?
Sahil Khanna

1

Tengo el mismo problema con el select2in bootstrap modal, y la solución fue eliminar el overflow-y: auto;y overflow: hidden; desde .modal-openy.modal classes

Aquí está el ejemplo del uso jQuerypara eliminar el overflow-y:

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

1

tuve este problema antes, estoy usando yii2 y lo resolví de esta manera

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

1

Tuve un problema semi relacionado en una aplicación, así que pondré mi 2c.

Tengo múltiples modales con formularios que contienen widgets select2. Abrir el modal A, luego otro modal dentro del modal A, provocaría que los widgets select2 dentro del modal B desaparezcan y no se inicialicen.

Cada uno de estos modales estaba cargando los formularios a través de ajax.

La solución fue eliminar los formularios del dom al cerrar 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

select2Resolví esto en general en mi proyecto sobrecargando la función. Ahora comprobará si no hay dropdownParent y si se llama a la función en un elemento que tiene un padre del tipodiv.modal . Si es así, agregará ese modal como padre para el menú desplegable.

De esta manera, no tiene que especificarlo cada vez que crea un cuadro de entrada select2.

(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

Simplemente lo hago funcionar incluyendo select2.min.css

Pruébalo

Mi html modal de bootstrap 3 es

<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

puede llamar al disparador select2 nuevamente dentro de su $ (documento)

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

0

para usar bootstrap 4.0 con el lado del servidor (datos en línea ajax o json), debe agregar todo esto:

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

y luego, cuando modal esté abierto, cree select2:

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

-1

En mi caso hice esto y funciona. Uso el paquete para cargarlo y en este caso funcionó para mí

 $(document).on('select2:select', '#Id_Producto', function (evt) {
   // Here your code...
  });
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.