javascript jquery ajax jsf-2 primefaces

javascript - JSF/PrimeFaces ajax updates rompe jQuery event listener function bindings



jsf-2 (1)

Estoy registrando un detector de eventos de change para cada input en el HTML usando jQuery como se muestra a continuación:

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

Ambos eventos de change se activan si el usuario cambia el contenido de myTextarea . Sin embargo, después de presionar el botón de actualización, que actualiza parcialmente myTextarea , solo se activará changeHandler posteriormente. El evento enlazado en $(document).ready() ya no se está desencadenando.

¿Está relacionado con PrimeFaces y / o con un comportamiento esperado? En caso afirmativo, ¿cómo puedo asegurar que active el segundo evento sin volver a ejecutar el script listo para documentos otra vez?


En cuanto a la causa de su problema, la solicitud ajax actualizará el árbol HTML DOM con nuevos elementos HTML de la respuesta ajax. Esos nuevos elementos HTML -obviamente- no tienen asociada la función del controlador de eventos jQuery. Sin embargo, $(document).ready() no se vuelve a ejecutar en las solicitudes ajax. Necesita volver a ejecutarlo manualmente.

Esto se puede lograr de varias maneras. La forma más simple es usar $(document).on(event, selector, function) lugar de $(selector).on(event, function) . Esto está relacionado con el documento y la eventName dada siempre se invoca cuando se activa el eventName dado en un elemento que coincide con el selector dado. Por lo tanto, nunca tendrá que volver a ejecutar explícitamente la función por medios JSF.

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

La forma alternativa es volver a ejecutar explícitamente la función usted mismo al completar la solicitud ajax. Esta sería la única forma en que realmente está interesado en ejecutar la función de inmediato durante el evento ready / load (por ejemplo, para aplicar directamente algún comportamiento específico del complemento / look''n''feel, como los selectores de fecha). En primer lugar, debe refactorizar el trabajo $(document).ready() en una función reutilizable de la siguiente manera:

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

(Tenga en cuenta que $.each() y simplifiqué su $.each() completamente innecesario)

Luego, elija una de las siguientes formas para volver a ejecutarlo cuando se complete la solicitud de ajax:

  1. Use el atributo oncomplete del botón de comando PrimeFaces:

    oncomplete="applyChangeHandler()"

  2. Utilice <h:outputScript target="body"> lugar de $(document).ready() ,

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

    y referenciarlo en el atributo de update :

    update=":applyChangeHandler"

  3. Utilice <p:outputPanel autoUpdate="true"> para actualizarlo automáticamente en cada solicitud de Ajax:

    <p:outputPanel autoUpdate="true"> <h:outputScript id="applyChangeHandler"> applyChangeHandler(); </h:outputScript> </p:outputPanel>

  4. Utilice OmniFaces <o:onloadScript> lugar de $(document).ready() , <h:outputScript> y todo en em.

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