O Select2 não funciona quando incorporado a um modal de inicialização

338

Quando uso um select2 (entrada) no modal de inicialização, não consigo digitar nada nele. É como desativado? Fora do modal select2 funciona bem.

insira a descrição da imagem aqui

Exemplo de trabalho: 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>

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

respostas:

aqui você pode encontrar uma solução rápida

e aqui está 'o caminho certo': Select2 não funciona quando incorporado em um modal de autoinicialização

breq
fonte
11
Ou seja, removendo o atributo tabindex = "- 1" do elemento
Nikit Barochiya
A resposta do dboswell é a solução certa, MAS, a dropdownParentnão deve estar na raiz div, mas mais profunda, por exemplo, a div com classe modal-content, caso contrário, as posições suspensas ficam confusas ao rolar o modal.
Shahin Dohan

Respostas:

606

Ok, eu tenho que trabalhar.

mudança

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

para

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

(remova tabindex = "- 1" do modal)

breq
fonte
22
Pode haver outra solução? Porque a janela modal não será fechada pela tecla Esc.
Wo-
19
remover tabindex = "- 1" não funcionou comigo. Acabei de alterar <div class = "modal-body"> para <div class = "modal-body" style = "overflow: hidden;">
Wissem
39
Como diabos você descobriu isso?
DontVoteMeDown
6
Eu tentei todas as opções, mas nada funciona para mim. Estou usando o select2 4.0
Girish Gupta 4/15
7
Obrigado! Faz 4 anos e ainda é uma correção válida.
Linek
248

Para Select2 v4:

Use dropdownParentpara anexar o menu suspenso à caixa de diálogo modal, em vez do 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>

Isso anexará o menu suspenso Select2 para que ele se enquadre no DOM do modal e não no corpo do HTML (o padrão). Consulte https://select2.org/dropdown#dropdown-placement

dboswell
fonte
12
Confirmado, isso está funcionando como um encanto e parece ser a melhor solução para esse problema!
Lacco
29
Isso funcionou para mim (com v4.0.2), mas eu tive que usar dropdownParent: $("#myModal"), não dropdownParent: "#myModal".
Saxon Druce
6
FWIW, no meu caso, eu precisava definir o dropdownParent no corpo do modal, anexá-lo ao modal em si não elevou o índice z alto o suficiente. por exemplo, dropdownParent: $ ('. modal-body', '#myModal')
DrewInTheMountains
11
Isso funciona perfeitamente bem sem remover o tabindex. +1
sammry
11
@DrewInTheMountains Eu também tive problemas para definir a dropdownParentraiz do modal, é realmente melhor escolher o corpo, caso contrário, você recebe erros de posicionamento muito ruins ao rolar. Defino o meu para o div com classe modal-contente funciona como um encanto!
Shahin Dohan
193

Eu encontrei uma solução para isso no github para select2

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

Para o bootstrap 3, a solução é:

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

O Bootstrap 4 renomeou o enforceFocusmétodo para _enforceFocus, então você precisará corrigi-lo:

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

Explicação copiada do link acima:

O Bootstrap registra um ouvinte no evento focusin que verifica se o elemento focado é a sobreposição em si ou um descendente dela - se não, ele apenas se concentra novamente na sobreposição. Com o menu suspenso select2 sendo anexado ao corpo, isso evita que você insira qualquer coisa no campo de texto.

Você pode corrigir isso substituindo a função enforceFocus que registra o evento no modal

pymarco
fonte
11
@pymarco Esse deveria estar lá um pouco antes para ser escolhido como resposta! Obrigado cara, por fornecer uma resposta real a um problema realmente irritante.
Ilter
3
@pymarco Esta é a solução correta. Obrigado por economizar meu tempo.
VKPRO 12/01
2
Você me poupou muito tempo com um problema que nem sempre criava sua cabeça. Obrigado!
precisa saber é o seguinte
11
Isso funcionou para mim !! Eu estava navegando pelos tópicos de problemas do select2 no github e não encontrei a postagem que você forneceu. Foi pesquisando e encontrando esta página no stackoverflow o que salvou minha vida. Obrigado!
Luis.ap.uyen
2
onde coloco esse código e qual função ele deve endereçar? Desculpe, JS noob aqui, tentei fazer parte do JS select2 ou colocá-lo no topo / final da página, tudo sem sucesso. $.fn.modal.Constructor.prototype.enforceFocus = $.noop;
Armitage2k
39

Basta remover tabindex="-1"e adicionar estilooverflow:hidden

Aqui está um exemplo:

<div id="myModal" class="modal fade" role="dialog" style="overflow:hidden;">
    <!---content modal here -->
</div>
MrBii
fonte
funciona, mas quando tenho um modal longo, não consigo rolar para baixo!
Tarek Kalaji 17/03/2019
11
@TarekKalaji, você já descobriu como permitir a rolagem com esta solução?
OverflowingTheGlass
Tentei remover o tabindex, mas não era suficiente. Adicionando overflow: hidden é útil se a caixa modal é longa ...
Plasebo
Trabalhou para remover o atributo de índice da guia.
Glen
Apenas para sua informação: remover o atributo tab-index remove a capacidade de fechar o popup modal pelo botão esc.
curiousBoy
31
.select2-close-mask{
    z-index: 2099;
}
.select2-dropdown{
    z-index: 3051;
}

Esta é a minha solução com o select2 4.0.0. Basta substituir o css logo abaixo da importação select2.css. Verifique se o índice z é maior que o seu diálogo ou modal. Acabei de adicionar 2000 nos padrões. Porque o índice z dos meus diálogos é de cerca de 1000.

Diluka W
fonte
11
Nenhuma das soluções funcionou para o select2 4.0.0, exceto isso. Muito obrigado.
Neel
O mesmo problema ocorre se o Select2 (v4.0.0) estiver em um popover. No bootstrap.cssz-index de .popoveré definido como 1060, portanto, essa correção também funciona. Gosto porque é simples e resolve o problema da mesma maneira que o problema foi criado: z-index definido em uma folha de estilos.
Paul
2
A solução mais trivial e a única que funcionou. Obrigado!
Ishtiaque Khan
Eu adicionei o acima no meu arquivo css, mas ele não tem alterações. Estou usando o jQuery Mobile. Alguma sugestão, por favor?
Sahil Khanna
@Sahil 1. verifique se ele substituiu com sucesso os originais. maneira simples é adicionar isso depois de todo o css padrão files2.check o índice z, garantir que ele é maior do que o do diálogo
Diluka W
26

Defina o dropdownParent. Eu tive que colocá-lo no conteúdo .modal dentro do modal ou o texto acabaria centralizado.

$("#product_id").select2({
    dropdownParent: $('#myModal .modal-content')
});
bezz
fonte
2
O .modal-contentrealmente fazer a diferença. Obrigado por apontar 👍
Js Lim
Isso funcionou para mim. Eu me pergunto por que isso não recebeu tantos votos positivos.
Chrisbjr
Trabalhou para mim também obrigado
Neha
11

Resposta que funcionou para mim encontrada aqui: https://github.com/select2/select2-bootstrap-theme/issues/41

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

Também não requer a remoção do tabindex.

Ashraf Slamang
fonte
Esta é a maneira mais agradável, também mantém todas as funcionalidades do modal.
Edofre 21/02
9

De acordo com a documentação oficial do select2, esse problema ocorre porque os modais de Bootstrap tendem a roubar o foco de outros elementos fora do modal.

Por padrão, o Select2 anexa o menu suspenso ao elemento e é considerado "fora do modal".

Em vez disso, anexe o menu suspenso ao próprio modal com a configuração dropdownParent:

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

Consulte a referência: https://select2.org/trou Troubleshooting / common - problems

Anas
fonte
Boa. ele não estava funcionando com pop-up magnífico, agora, depois de adicionar a opção dropdownParent, está funcionando bem.
Yogesh Saroya
8

Eu tive o mesmo problema, a atualização z-indexpara .select2-containerdeve fazer o truque. Verifique se o modal z-indexé menor que o select2.

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

Atualizado: caso o código acima não funcione corretamente, remova também os índices de tabulação do seu modal, como sugerido pelo @breq

hhk
fonte
11
você precisa implementar isso com a resposta @breq para fazê-lo funcionar.
Ryan Arief
7

Basta usar esse código em Document.read ()

$.fn.modal.Constructor.prototype.enforceFocus = function () {};
S.Mohamed Mahdi Ahmadian zadeh
fonte
11
O nome da função apropriada é "$ (document) .ready". Portanto, o código deve ser como: $ (document) .ready (function () {$ .fn.modal.Constructor.prototype.enforceFocus = function () {};});
Lech Osiński
11
@ LechOsiński - Obrigado por realmente descrever como usar esse pequeno pedaço de código. Sua solução é a única que funcionou para mim. +1
Francis Bartkowiak
7

Este problema é o trabalho para mim Função Jquery única

$('#myModal .select2').each(function() {  
   var $p = $(this).parent(); 
   $(this).select2({  
     dropdownParent: $p  
   });  
});
Vinoth Smart
fonte
Obrigado! Isso resolveu o meu problema
Mihai Alexandru-Ionut
5

alterar o arquivo select2.css

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

para

z-index: 10000;
...
z-index: 10001;
...
z-index: 10002;
user1616435
fonte
Esse é o único que funciona para mim (jquery-ui-1.10.3.css, jquery-ui-1.9.1.js e select2 3.4.0). Eu tenho 2 caixas de diálogo jquery UI, uma em cima da outra e select2 na segunda. Também coloquei // permitir interação do select2, selecionador de data e hora na caixa de diálogo jQuery UI $ .ui.dialog.prototype._allowInteraction = function (e) {return !! $ (e.target) .closest ('. Ui- diálogo, .ui-datepicker, .select2-drop '). length; }; Eu não tenho idéia se isso ajuda ou não.
Adrian P.
5

Apenas para entender melhor como os elementos tabindex funcionam para concluir a resposta aceita:

O atributo global tabindex é um número inteiro indicando se o elemento pode receber o foco de entrada (é focalizável), se deve participar da navegação seqüencial do teclado e, em caso afirmativo, em que posição. Pode levar vários valores:
  -um valor negativo significa que o elemento deve ser focável, mas não deve ser acessível via navegação seqüencial no teclado;
  -0 significa que o elemento deve ser focável e alcançável através da navegação seqüencial do teclado, mas sua ordem relativa é definida pela convenção da plataforma;
  -um meio de valor positivo deve ser focalizável e alcançável através da navegação sequencial do teclado; sua ordem relativa é definida pelo valor do atributo: o seqüencial segue o número crescente do índice de tabulação. Se vários elementos compartilham o mesmo índice de tabulação, sua ordem relativa segue sua posição relativa no documento.

de: Mozilla Devlopper Network

538ROMEO
fonte
3

Se você tiver um problema com o teclado do iPad que oculta o modal de autoinicialização enquanto clica na entrada select2 , você pode resolver isso adicionando a seguinte regra após a inicialização da 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
}

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

EDIT: Se suas opções não forem mostradas corretamente, você precisará usar o dropdownParentatributo ao inicializar select2:

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

Boa sorte (:

Gangai Johann
fonte
3

Com base na resposta @pymarco que escrevi esta solução, ela não é perfeita, mas resolve o problema de foco select2 e mantém a sequência de guias funcionando dentro do 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))
    }
Angelo Cavalet
fonte
3

No meu caso, tive o mesmo problema com dois modais e tudo foi resolvido usando:

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

Como na edição do projeto # 41, um usuário disse.

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

este código está funcionando. Obrigado.

ramazan polat
fonte
2

Ok, eu sei que estou atrasado para a festa. Mas deixe-me compartilhar com você o que funcionou para mim. As soluções tabindex e z-index não funcionaram para mim.

A configuração do pai do elemento select funcionou de acordo com os problemas comuns listados no site select2.

palhaço
fonte
1

Se você usar o jquery mobile popup, deverá reescrever a função _handleDocumentFocusIn:

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

Dr. Clò Luca
fonte
Estou usando o jQuery Mobile e incorporamos o Select2 em um pop-up. O código que você forneceu funciona bem em um navegador de PC. Mas quando executo esse código em um navegador móvel, o pop-up fecha e reabre quando qualquer valor é selecionado. Você pode sugerir alguma alteração que eu precise fazer?
Sahil Khanna
1

Eu tenho o mesmo problema com o select2in bootstrap modale a solução foi remover o overflow-y: auto;e overflow: hidden; de .modal-opene.modal classes

Aqui está o exemplo do uso jQuerypara remover o overflow-y:

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

eu tive esse problema antes, estou usando o yii2 e resolvi dessa maneira

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

Eu tive um problema semi-relacionado em um aplicativo, por isso vou colocar no meu 2c.

Eu tenho vários modais com formulários contendo widgets select2. Abrir o modal A, em seguida, outro modal dentro do modal A, faria com que os widgets select2 dentro do modal B desaparecessem e falhassem na inicialização.

Cada um desses modais estava carregando os formulários via ajax.

A solução foi remover os formulários do Dom ao fechar um modal.

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

Resolvi isso geralmente no meu projeto sobrecarregando a select2função-. Agora ele verificará se não há dropdownParent e se a função é chamada em um elemento que possui um pai do tipo div.modal. Nesse caso, ele adicionará esse modal como pai do menu suspenso.

Dessa forma, você não precisa especificá-lo toda vez que criar uma caixa de seleção-2-entrada.

(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
fonte
0

Acabei de trabalhar incluindo select2.min.css

Experimente o iy

Meu html modal do 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>
Desenvolvedor
fonte
0

você pode chamar o gatilho select2 novamente dentro do seu $ (documento)

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

Para usar o bootstrap 4.0 com o lado do servidor (dados ajax ou json inline), você precisa adicionar tudo isso:

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

e quando o modal estiver aberto, crie o select2:

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

No meu caso, eu fiz isso e funciona. Eu uso o pacote para carregá-lo e, neste caso, funcionou para mim

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