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


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)


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


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


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>

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.


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

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


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


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


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

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

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;

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


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


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

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.


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

este código está funcionando. Obrigado.


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.


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


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

1

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

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

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

1
$('.modal').on('shown.bs.modal', function (e) {
    $(this).find('.select2me').select2({
        dropdownParent: $(this).find('.modal-content')
    });
})

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

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>

0

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

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

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({
                  // ....
            });
  });

-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...
  });
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.