javascript JSF/PrimeFaces ajax 更新破坏了 jQuery 事件侦听器函数绑定

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14400624/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 21:32:18  来源:igfitidea点击:

JSF/PrimeFaces ajax updates breaks jQuery event listener function bindings

javascriptjqueryajaxjsf-2primefaces

提问by Uluk Biy

I am registering a changeevent listener for every inputin the HTML using jQuery as below:

我正在使用 jQuery 为 HTML 中的change每个注册一个事件侦听器,input如下所示:

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

Both changeevents are being triggered if the user changes the content of myTextarea. However after pressing the update button, which partially updates the myTextarea, only the changeHandler is triggering afterwards. The event bound in $(document).ready()is not triggering anymore.

change如果用户更改 的内容,则会触发这两个事件myTextarea。然而,在按下更新按钮后,它会部分更新myTextarea,之后只有 changeHandler 被触发。绑定的事件$(document).ready()不再触发。

Is this PrimeFaces related and/or an expected behavior? If yes then how can I ensure to trigger the second event without rerunning document ready script again.

这是 PrimeFaces 相关和/或预期行为吗?如果是,那么如何确保在不重新运行文档就绪脚本的情况下触发第二个事件。

回答by BalusC

As to the cause of your problem, the ajax request will update the HTML DOM tree with new HTML elements from the ajax response. Those new HTML elements do —obviously— not have the jQuery event handler function attached. However, the $(document).ready()isn't re-executed on ajax requests. You need to manually re-execute it.

至于您的问题的原因,ajax 请求将使用来自 ajax 响应的新 HTML 元素更新 HTML DOM 树。这些新的 HTML 元素——显然——没有附加 jQuery 事件处理函数。但是,$(document).ready()不会在 ajax 请求上重新执行。您需要手动重新执行它。

This can be achieved in various ways. The simplest way is to use $(document).on(event, selector, function)instead of $(selector).on(event, function). This is tied to the document and the given functionRefis always invoked when the given eventNameis triggered on an element matching the given selector. So you never need to explicitly re-execute the function by JSF means.

这可以通过多种方式实现。最简单的方法是使用$(document).on(event, selector, function)代替$(selector).on(event, function)。这与文档相关联,并且在匹配给定的元素上触发给定时functionRef总是调用给eventNameselector。因此,您永远不需要通过 JSF 方式显式地重新执行该函数。

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


The alternative way is to explicitly re-execute the function yourself on complete of ajax request. This would be the only way when you're actually interested in immediately execute the function during the ready/loadevent (e.g. to directly apply some plugin specific behavior/look'n'feel, such as date pickers). First, you need to refactor the $(document).ready()job into a reusable function as follows:

另一种方法是在 ajax 请求完成时自己显式地重新执行该函数。当您真正有兴趣在ready/load事件期间立即执行函数时,这将是唯一的方法(例如,直接应用某些插件特定的行为/外观,例如日期选择器)。首先,您需要将$(document).ready()作业重构为可重用的函数,如下所示:

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

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

(note that I removed and simplified your completely unnecessary $.each()approach)

(请注意,我删除并简化了您完全不必要的$.each()方法)

Then, choose one of the following ways to re-execute it on complete of ajax request:

然后,选择以下方式之一在ajax请求完成时重新执行它:

  1. Use the oncompleteattribute of the PrimeFaces command button:

    oncomplete="applyChangeHandler()"
    
  2. Use <h:outputScript target="body">instead of $(document).ready(),

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

    and reference it in updateattribute:

    update=":applyChangeHandler"
    
  3. Use <p:outputPanel autoUpdate="true">to auto update it on every ajax request:

    <p:outputPanel autoUpdate="true">
        <h:outputScript id="applyChangeHandler">
            applyChangeHandler();
        </h:outputScript>
    </p:outputPanel>
    
  4. Use OmniFaces<o:onloadScript>instead of $(document).ready(), <h:outputScript>and all on em.

    <o:onloadScript>applyChangeHandler();</o:onloadScript>
    
  1. 使用oncompletePrimeFaces 命令按钮的属性:

    oncomplete="applyChangeHandler()"
    
  2. 使用<h:outputScript target="body">代替$(document).ready()

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

    并在update属性中引用它:

    update=":applyChangeHandler"
    
  3. 用于<p:outputPanel autoUpdate="true">在每个 ajax 请求上自动更新它:

    <p:outputPanel autoUpdate="true">
        <h:outputScript id="applyChangeHandler">
            applyChangeHandler();
        </h:outputScript>
    </p:outputPanel>
    
  4. 在 em 上使用OmniFaces<o:onloadScript>而不是$(document).ready(), <h:outputScript>

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