установка datepicker () на динамически создаваемые элементы - JQuery / JQueryUI


116

У меня есть динамически созданные текстовые поля, и я хочу, чтобы каждое из них могло отображать календарь при нажатии. Я использую следующий код:

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

Это будет работать только с первым текстовым полем, хотя все мои текстовые поля имеют класс с именем datepicker_recurring_start.

Ваша помощь очень ценится!


Когда вы говорите «динамически создается», вы имеете в виду с кодом программной части до загрузки страницы или с javascript после загрузки страницы? Потому что, если элементы добавляются после загрузки страницы, вам нужно будет заново привязать календарь каждый раз, когда добавляется новое текстовое поле.
DangerMonkey

Я загружаю его в код программной части с помощью PHP.
круто

Я думаю, вы можете запутаться, но тогда трудно сказать с той информацией, которую вы предоставили. Итак, чтобы подтвердить, не могли бы вы подтвердить, что вы имеете в виду под «динамически создаваемыми текстовыми полями», пожалуйста.
Tr1stan

Если я загружаю «страницу один», php смотрит на базу данных, чтобы узнать, сколько текстовых полей даты находится на «первой странице», и отображает его. Поэтому, когда загружается «первая страница», будет 4 текстовых поля, в которые нужно загрузить datepicker (). На второй странице есть 7 текстовых полей, в которые необходимо загрузить функцию datepicker ().
круто

Если у вас есть проблема с тем, что сборщик данных не работает после первого вызова, ознакомьтесь с этим ответом: stackoverflow.com/a/16283547/1329910 Возможно, ваша проблема связана с datepicker, добавляющим свой собственный класс: hasDatepicker
Влад

Ответы:


271

вот трюк:

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

DEMO

В $('...selector..').on('..event..', '...another-selector...', ...callback...);синтаксических средств:
Добавить слушателя ...selector..( bodyв нашем примере) для события ..event..( «фокус» в нашем примере). Для всех потомков совпадающих узлов, которые соответствуют селектору ...another-selector...( .datepicker_recurring_startв нашем примере), примените обработчик событий ...callback...(встроенная функция в нашем примере)

См. Http://api.jquery.com/on/ и особенно раздел о «делегированных событиях».


4
Это решение, которое будет работать с любым типом динамического добавления. +1 к вам.
DangerMonkey

5
Хотя мне кажется странным, что вы хотите вызывать .datapicker()каждый раз, когда текстовое поле получает фокус, поэтому вы должны быть осторожны с этим подходом (при условии, что я правильно это читаю). Однако я думаю, что вы будете в порядке, .datapicker()потому что он, вероятно, проверит, создан ли datepicker, прежде чем пытаться воссоздать. С другим кодом у вас может не быть этой изящества. Кроме того, .on (представлен только в JQuery 1.7, поэтому убедитесь, что вы используете правильную версию.
Tr1stan,

3
datepicker достаточно умен, чтобы проверить, создан ли он уже или нет (кстати, все компоненты jQueryUI), если версия jQuery ниже 1.7, вы можете просто использовать live
ilyes kooli

7
Возможно, вы захотите добавить фильтр:not(.hasDatepicker)
Salman A

1
Остерегайтесь использования jQuery.clone () внутри области, содержащей указатель даты. Если вы это сделаете, добавьте это, чтобы удалить класс hasDatepicker И идентификатор datepicker добавляет к вашему вводу: .... find ('input.hasDatepicker'). RemoveClass ('hasDatepicker'). RemoveAttr ('id');
yahermann

45

Для меня ниже работал jquery:

изменение "тела" на документ

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

Спасибо скафандри

Примечание: убедитесь, что ваш идентификатор отличается для каждого поля


Правильно - для меня я должен использовать $ (document), а не $ ('body') - своего рода проблема с небольшими фрагментами кода. Я могу заставить этот пример работать без проблем, но как только я добавлю кучу своего javascript в скрипт, этот код больше не работает для меня. Но спасибо обоим.
Tom Stickel 06

16

Отличный ответ скафандри +1

Он обновлен только для проверки наличия класса hasDatepicker.

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

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

});

1
Можно ли тогда сократить это до $('body').on('focus',".datepicker:not(.hasDatepicker)", function(){$(this).datepicker();});?
Люк Стивенсон

11

Убедитесь, что у вашего элемента с .date-pickerклассом еще нет hasDatepickerкласса. Если это произойдет, даже попытка повторной инициализации с помощью $myDatepicker.datepicker();не удастся! Вместо этого вам нужно сделать ...

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

Совершенно верно! Динамически загружаемые элементы для меня не были проблемой, поэтому это решение сработало.
Стерлинг Бисон,

6

Вам нужно запустить .datepicker();снова после того, как вы динамически создали другие элементы текстового поля.

Я бы рекомендовал сделать это в методе обратного вызова вызова, который добавляет элементы в DOM.

Допустим, вы используете метод JQuery Load для извлечения элементов из источника и загрузки их в DOM, вы бы сделали что-то вроде этого:

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

1
По моему опыту, это не всегда работает на практике. Лучше всего добавить уникальные идентификаторы к вашим элементам и использовать эти идентификаторы для ссылки на них и применить средство выбора даты. Похоже, что плагин внутренне использует эти селекторы.
Уэс Джонсон,

1

Новый метод для динамических элементов - MutationsObserver .. В следующем примере используется underscore.js для использования функции (_.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
});


0

Ни одно из других решений не помогло мне. В моем приложении я добавляю в документ элементы диапазона дат с помощью jquery, а затем применяю к ним datepicker. Так что ни одно из событийных решений почему-то не сработало.

Вот что в итоге сработало:

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

Надеюсь, это кому-то поможет, потому что это немного отбросило меня назад.


0

вы можете добавить класс .datepicker в функцию javascript, чтобы иметь возможность динамически изменять тип ввода

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

0

Я изменил ответ @skafandri, чтобы избежать повторного применения datepickerконструктора ко всем входам с .datepicker_recurring_startклассом.

Вот HTML:

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

Вот JS:

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

вот рабочая демонстрация


0

Это то, что сработало для меня в JQuery 1.3 и отображается при первом щелчке / фокусе

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

для этого необходимо, чтобы ваш ввод имел класс mostrar_calendario

Live предназначен для JQuery 1.3+, для более новых версий вам необходимо адаптировать это к "on"

Подробнее о разнице можно узнать здесь http://api.jquery.com/live/


0
$( ".datepicker_recurring_start" ).each(function(){
    $(this).datepicker({
        dateFormat:"dd/mm/yy",
        yearRange: '2000:2012',
        changeYear: true,
        changeMonth: true
    });
});
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.