Подтвердить что ты не робот

JSF/PrimeFaces ajax обновляет разрывы jQuery.

Я регистрирую прослушиватель событий change для каждого input в HTML, используя jQuery, как показано ниже:

<h:head>
    <script type="text/javascript">
        //<![CDATA[
        $(document).ready(function(){
            $(':input').each(function() {
                $(this).change(function() {
                    console.log('From docReady: ' + this.id);
                });
            });
        });

        function changeHandler() {
            console.log("from changeHandler");
        }
        //]]>
    </script>
</h:head>
<h:body>
    <h:form id="topForm">
        <p:commandButton id="myButton" value="update"
                         action="#{testBean.submit}"
                         partialSubmit="true" process=":myForm:panel"
                         update=":myForm:panel" />
    </h:form>
    <h:form id="myForm">
        <p:panel id="panel">
            <p:inputTextarea id="myTextarea"
                             value="#{testBean.val}"
                             onchange="changeHandler();"/>
        </p:panel>
    </h:form>
</h:body>

Оба события change запускаются, если пользователь изменяет содержимое myTextarea. Однако после нажатия кнопки обновления, которая частично обновляет myTextarea, запускается только changeHandler. Событие, связанное в $(document).ready(), больше не запускается.

Связано ли это и/или ожидаемое поведение PrimeFaces? Если да, то как я могу обеспечить запуск второго события без повторной перезагрузки документа script.

4b9b3361

Ответ 1

Что касается причины вашей проблемы, запрос ajax обновит дерево DOM HTML новыми элементами HTML из ответа ajax. Эти новые HTML-элементы действительно выглядят, очевидно,— не подключена функция обработчика событий jQuery. Тем не менее, $(document).ready() не выполняется повторно в запросах ajax. Вам необходимо выполнить его повторное выполнение вручную.

Это может быть достигнуто различными способами. Самый простой способ - использовать $(document).on(event, selector, function) вместо $(selector).on(event, function). Это привязано к документу, и данный functionRef всегда вызывается, когда заданный eventName запускается на элементе, соответствующем данному selector. Таким образом, вам не нужно явно повторно выполнять функцию средствами JSF.

$(document).on("change", ":input", function() {
    console.log("From change event on any input: " + this.id);
});

Альтернативный способ заключается в том, чтобы явно выполнить функцию самостоятельно при выполнении запроса ajax. Это было бы единственным способом, когда вы действительно заинтересованы в немедленном выполнении функции во время события ready/load (например, для непосредственного применения определенного поведения /look 'n'feel для плагина, например выбора даты). Во-первых, вам нужно реорганизовать задание $(document).ready() в функцию повторного использования следующим образом:

$(document).ready(function(){
    applyChangeHandler();
});

function applyChangeHandler() {
    $(":input").on("change", function() {
        console.log("From applyChangeHandler: " + this.id);
    });
}

(обратите внимание, что я удалил и упростил ваш совершенно ненужный подход $.each())

Затем выберите один из следующих способов повторного его выполнения при выполнении запроса ajax:

  • Используйте атрибут oncomplete кнопки команды PrimeFaces:

    oncomplete="applyChangeHandler()"
    
  • Используйте <h:outputScript target="body"> вместо $(document).ready(),

    <h:outputScript id="applyChangeHandler" target="body">
        applyChangeHandler();
    </h:outputScript>
    

    и ссылайтесь на него в атрибуте update:

    update=":applyChangeHandler"
    
  • Используйте <p:outputPanel autoUpdate="true"> для автоматического обновления по каждому запросу ajax:

    <p:outputPanel autoUpdate="true">
        <h:outputScript id="applyChangeHandler">
            applyChangeHandler();
        </h:outputScript>
    </p:outputPanel>
    
  • Используйте OmniFaces <o:onloadScript> вместо $(document).ready(), <h:outputScript> и всех на em.

    <o:onloadScript>applyChangeHandler();</o:onloadScript>