Javascript JSF/PrimeFaces ajax更新破坏了jQuery事件侦听器函数绑定
我正在使用jQuery为HTML中的每个Javascript JSF/PrimeFaces ajax更新破坏了jQuery事件侦听器函数绑定,javascript,jquery,ajax,jsf-2,primefaces,Javascript,Jquery,Ajax,Jsf 2,Primefaces,我正在使用jQuery为HTML中的每个输入注册change事件侦听器,如下所示: <h:head> <script type="text/javascript"> //<![CDATA[ $(document).ready(function(){ $(':input').each(function() { $(this).change(function() {
输入注册change
事件侦听器,如下所示:
<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>
//
如果用户更改myTextarea
的内容,则会触发两个change
事件。但是,在按下部分更新myTextarea
的更新按钮后,只有changeHandler随后触发。$(document).ready()
中绑定的事件不再触发
这是相关的和/或预期的行为吗?如果是,那么如何确保触发第二个事件而不再次运行document ready脚本。至于问题的原因,ajax请求将使用ajax响应中的新HTML元素更新HTML DOM树。显然,这些新的HTML元素没有附加jQuery事件处理程序函数。但是,$(document).ready()
不会在ajax请求上重新执行。您需要手动重新执行它
这可以通过多种方式实现。最简单的方法是使用$(文档).on(事件、选择器、函数)
而不是$(选择器).on(事件、函数)
。这与文档相关,并且当在与给定的选择器
匹配的元素上触发给定的事件名
时,始终会调用给定的函数ref
。因此,您永远不需要通过JSF方式显式地重新执行函数
$(document).on("change", ":input", function() {
console.log("From change event on any input: " + this.id);
});
另一种方法是在完成ajax请求后自己显式地重新执行函数。这是在ready
/load
事件期间(例如,直接应用某些特定于插件的行为/外观,如日期选择器)您真正有兴趣立即执行函数的唯一方法。首先,您需要将$(document).ready()作业重构为可重用函数,如下所示:
$(document).ready(function(){
applyChangeHandler();
});
function applyChangeHandler() {
$(":input").on("change", function() {
console.log("From applyChangeHandler: " + this.id);
});
}
(请注意,我删除并简化了完全不必要的$.each()
方法)
然后,选择以下方法之一在ajax请求完成时重新执行它:
<p:outputPanel autoUpdate="true">
<h:outputScript id="applyChangeHandler">
applyChangeHandler();
</h:outputScript>
</p:outputPanel>
使用PrimeFaces命令按钮的oncomplete
属性:
oncomplete="applyChangeHandler()"
使用
而不是$(document).ready()
使用
在每次ajax请求时自动更新:
<p:outputPanel autoUpdate="true">
<h:outputScript id="applyChangeHandler">
applyChangeHandler();
</h:outputScript>
</p:outputPanel>
或者您可以使用,这是专门为解决此类问题而设计的技术。@Anthony:这仅适用于通过“普通jQuery”执行的ajax请求和通过“普通jQuery”附加的HTML DOM元素因为它有自己的内部事件监听器。我所有的经验告诉我,这两种说法都不正确。@BalusC。谢谢你的发帖。第三种选择似乎适合我的用例。我计划将该代码块放在facelet模板中。对于第三种方法,我删除了$(document).ready(function(){}否则处理程序在初始页面加载时会注册两次,然后手动将可自动更新的p:outputPanel放在正文的末尾。如果我最终发现自己实现了Omnifaces已经提供的功能,我肯定会尝试一下。:@BalusC。有没有办法只在ajax响应之后在新添加的元素上执行脚本?否则,处理程序会一次又一次地绑定到元素。
<p:outputPanel autoUpdate="true">
<h:outputScript id="applyChangeHandler">
applyChangeHandler();
</h:outputScript>
</p:outputPanel>
<o:onloadScript>applyChangeHandler();</o:onloadScript>