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!

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

ilyes kooli
fonte
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

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

});
fofo
fonte
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();
Wintondeshong
fonte
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();
});
Tr1stan
fonte
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
});
Hady Shaltout
fonte
1

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

$('body').on('focus', '.datepicker', function() {
 $(this).removeClass('hasDatepicker').datepicker();
});
Vinicius Avelino Alcantara
fonte
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.

Chris
fonte
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', });
Nada N. Hantouli
fonte
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

c0x6a
fonte
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/

Mauricio Gracia Gutierrez
fonte
0
$( ".datepicker_recurring_start" ).each(function(){
    $(this).datepicker({
        dateFormat:"dd/mm/yy",
        yearRange: '2000:2012',
        changeYear: true,
        changeMonth: true
    });
});
Siya Qalistic
fonte