colocar datepicker () em elementos criados dinamicamente - JQuery / JQueryUI


115

Eu criei caixas de texto dinamicamente e quero que cada uma delas seja capaz de exibir um calendário com um clique. O código que estou usando é:

$(".datepicker_recurring_start" ).datepicker();

Que só funcionará na primeira caixa de texto, embora todas as minhas caixas de texto tenham uma classe chamada datepicker_recurring_start.

Sua ajuda é muito apreciada!


Quando você diz "criado dinamicamente", quer dizer com code-behind antes de a página carregar ou com javascript após o carregamento da página? Porque se os elementos forem adicionados após o carregamento da página, você precisará religar o calendário sempre que uma nova caixa de texto for adicionada.
DangerMonkey

Estou carregando no code-behind com PHP.
mergulhado

Acho que você pode estar ficando confuso, mas é difícil dizer com as informações que você forneceu. Então, apenas para confirmar, você pode confirmar o que você entende por 'caixas de texto criadas dinamicamente', por favor.
Tr1stan

Se eu estou carregando a 'página um', o php olha o banco de dados para ver quantas caixas de texto de data estão na 'página um' e o exibe. Então, quando a 'página um' carregar, haverá 4 caixas de texto que precisam carregar o selecionador de data (). 'página dois' tem 7 caixas de texto que precisam carregar a função datepicker ().
mergulhado

Se você tiver um problema com o selecionador de dados não funcionando após uma primeira chamada, verifique esta resposta: stackoverflow.com/a/16283547/1329910 Seu problema pode ter a ver com o datepicker adicionando sua própria classe: hasDatepicker
Vlad

Respostas:


269

aqui está o truque:

$('body').on('focus',".datepicker_recurring_start", function(){
    $(this).datepicker();
});​

DEMO

A $('...selector..').on('..event..', '...another-selector...', ...callback...);sintaxe significa:
Adicionar um ouvinte ao ...selector..( bodyno nosso exemplo) para o evento ..event..('foco' no nosso exemplo). Para todos os descendentes dos nós correspondentes que correspondem ao seletor ...another-selector...( .datepicker_recurring_startem nosso exemplo), aplique o manipulador de eventos ...callback...(a função inline em nosso exemplo)

Veja http://api.jquery.com/on/ e especialmente a seção sobre "eventos delegados"


4
Esta é uma solução que funcionaria em qualquer tipo de acréscimo dinâmico. +1 para você.
DangerMonkey

5
Embora pareça estranho para mim que você queira chamar .datapicker()toda vez que a caixa de texto ganha foco - então você deve ter cuidado com essa abordagem (presumindo que estou lendo isso direito). No entanto, acho que você aceitaria o .datapicker()porque provavelmente verificará se um selecionador de data foi criado antes de tentar recriar. Com outro código, você pode não ter essa graça. Além disso, .on (só foi introduzido no JQuery 1.7 - certifique-se de usar a versão correta.
Tr1stan

3
datepicker é inteligente o suficiente para verificar se já foi criado ou não (todos os componentes jQueryUI a propósito) se a versão do jQuery está abaixo de 1.7 você pode simplesmente usar live
ilyes kooli

7
Você pode querer adicionar um filtro:not(.hasDatepicker)
Salman A

1
Cuidado ao usar jQuery.clone () dentro de uma área que inclui um selecionador de data. Se você fizer isso, adicione isto para remover a classe hasDatepicker E o id datepicker adiciona à sua entrada: .... find ('input.hasDatepicker'). RemoveClass ('hasDatepicker'). RemoveAttr ('id');
yahermann

44

Para mim, abaixo jquery funcionou:

alterando "corpo" para documento

$(document).on('focus',".datepicker_recurring_start", function(){
    $(this).datepicker();
});

Graças a skafandri

Nota: certifique-se de que seu id é diferente para cada campo


Correto - para mim eu tenho que usar $ (document) e não $ ('body') - Tipo de problema com pequenos trechos de código. Posso fazer o exemplo funcionar sem problemas, mas e assim que adiciono um monte de meu javascript em um violino, esse código não funciona mais para mim. Obrigado a ambos.
Tom Stickel

16

Excelente resposta por skafandri +1

Isso foi atualizado apenas para verificar a classe hasDatepicker.

$('body').on('focus',".datepicker", function(){

    if( $(this).hasClass('hasDatepicker') === false )  {
        $(this).datepicker();
    }

});

1
Isso poderia ser abreviado para $('body').on('focus',".datepicker:not(.hasDatepicker)", function(){$(this).datepicker();});?
Luke Stevenson

11

Certifique-se de que seu elemento com a .date-pickerclasse NÃO tenha uma hasDatepickerclasse. Se isso acontecer, mesmo uma tentativa de reinicialização com $myDatepicker.datepicker();falhará! Em vez disso, você precisa fazer ...

$myDatepicker.removeClass('hasDatepicker').datepicker();

Exatamente certo! Elementos carregados dinamicamente acabaram não sendo o problema para mim, então essa solução funcionou.
Sterling Beason

6

Você precisa executar o .datepicker();novamente depois de criar dinamicamente os outros elementos da caixa de texto.

Eu recomendaria fazer isso no método de retorno de chamada da chamada que está adicionando os elementos ao DOM.

Então, digamos que você esteja usando o método JQuery Load para extrair os elementos de uma fonte e carregá-los no DOM, você faria algo assim:

$('#id_of_div_youre_dynamically_adding_to').load('ajax/get_textbox', function() {
  $(".datepicker_recurring_start" ).datepicker();
});

1
Isso nem sempre funciona na prática, com base na minha experiência. O melhor caso é adicionar IDs exclusivos aos seus elementos e usar esses IDs para referenciá-los e aplicar o selecionador de data. Parece que internamente o plugin usa esses seletores.
Wes Johnson

1

O novo método para elementos dinâmicos é MutationsObserver . O exemplo a seguir usa underscore.js para usar a função (_.each).

MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;    

var observerjQueryPlugins = new MutationObserver(function (repeaterWrapper) {

    _.each(repeaterWrapper, function (repeaterItem, index) {

        var jq_nodes = $(repeaterItem.addedNodes);

        jq_nodes.each(function () {

            // Date Picker
            $(this).parents('.current-repeateritem-container').find('.element-datepicker').datepicker({
                dateFormat: "dd MM, yy",
                showAnim: "slideDown",
                changeMonth: true,
                numberOfMonths: 1
            });

        });

    });

});

observerjQueryPlugins.observe(document, {
    childList: true,
    subtree: true,
    attributes: false,
    characterData: false
});

1

Isso foi o que funcionou para mim (usando jquery datepicker):

$('body').on('focus', '.datepicker', function() {
 $(this).removeClass('hasDatepicker').datepicker();
});

0

Nenhuma das outras soluções funcionou para mim. Em meu aplicativo, estou adicionando os elementos de intervalo de datas ao documento usando jquery e, em seguida, aplicando datepicker a eles. Portanto, nenhuma das soluções do evento funcionou por algum motivo.

Isso é o que finalmente funcionou:

$(document).on('changeDate',"#elementid", function(){
    alert('event fired');
});

Espero que isso ajude alguém, porque isso me atrapalhou um pouco.


0

você pode adicionar a classe .datepicker em uma função javascript, para poder alterar dinamicamente o tipo de entrada

 $("#ddlDefault").addClass("datepicker");
 $(".datepicker").datetimepicker({ timepicker: false, format: 'd/m/Y', });

0

Modifiquei a resposta @skafandri para evitar reaplicar o datepickerconstrutor a todas as entradas com .datepicker_recurring_startclasse.

Aqui está o HTML:

<div id="content"></div>
<button id="cmd">add a datepicker</button>

Aqui está o JS:

$('#cmd').click(function() {
  var new_datepicker = $('<input type="text">').datepicker();
  $('#content').append('<br>a datepicker ').append(new_datepicker);
});

aqui está uma demonstração de trabalho


0

Isso é o que funcionou para mim no JQuery 1.3 e está mostrando no primeiro clique / foco

function vincularDatePickers() {
    $('.mostrar_calendario').live('click', function () {
        $(this).datepicker({ showButtonPanel: true, changeMonth: true, changeYear: true, showOn: 'focus' }).focus();
    });
}

isso precisa que sua entrada tenha a classe 'mostrar_calendario'

Live é para JQuery 1.3+. Para versões mais recentes, você precisa adaptá-lo para "on"

Veja mais sobre a diferença aqui http://api.jquery.com/live/


0
$( ".datepicker_recurring_start" ).each(function(){
    $(this).datepicker({
        dateFormat:"dd/mm/yy",
        yearRange: '2000:2012',
        changeYear: true,
        changeMonth: true
    });
});
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.