通过Ajax更新JSF组件后,JavaScript/jQuery事件侦听器不起作用 [英] JavaScript/jQuery event listeners do not work after JSF component is updated via Ajax
问题描述
我正在<p:dataTable>
过滤器(其ID为id
)上执行以下jQuery函数,该过滤器允许用户在过滤器组件中仅输入数字.
I'm executing the following jQuery function on <p:dataTable>
filter (whose id is id
) that allows users to enter only digits in the filter component.
$(document).ready(function() {
$("#form\\:dataTable\\:id\\:filter").keydown(function(event) {
//Allow: tab, escape, and enter
if(event.keyCode===9||event.keyCode===27||event.keyCode===13||
//Allow: Ctrl+A, Ctrl+C
(event.keyCode===65&&event.ctrlKey===true)||(event.keyCode===67&&event.ctrlKey===true)||
//Allow: home, end, left, right
(event.keyCode>=35&&event.keyCode<=39)){
//let it happen, don't do anything
event.preventCapture();
return;
}//backspace, delete
else if(event.keyCode===46||event.keyCode===8)
{
return;
}
else{//Ensure that it is a number and stop the keypress
if (event.shiftKey||(event.keyCode<48||event.keyCode>57)&&(event.keyCode< 96||event.keyCode>105)){
//event.preventDefault();
event.preventCapture();
}
}
});
});
此功能位于context/resources/default/js/digit_only_textfield.js
下.因此,它可以在XHTML页面上使用,
This function is placed under context/resources/default/js/digit_only_textfield.js
. Therefore, it can be used on XHTML pages like,
<h:outputScript library="default" name="js/digit_only_textfield.js"/>
XHTML页面如下所示.
The XHTML page looks like the following.
<h:outputScript library="default" name="js/digit_only_textfield.js"/>
<h:form id="form" prependId="true">
<!--PrimeFaces extension <pe:blockUI>-->
<p:remoteCommand name="updateTable" update="dataTable"/>
<p:panel id="panel">
<h:panelGrid id="panelGrid" columns="3" cellpadding="5">
<!--Some UIInput components-->
<p:commandButton id="btnSubmit"
update="panel"
onstart="PF('blockUIWidget').block();"
oncomplete="if(!args.validationFailed) {updateTable();}PF('blockUIWidget').unblock();"
actionListener="#{bean.insert}"
value="Save"/>
</h:panelGrid>
</p:panel>
<p:dataTable id="dataTable"
var="row"
value="#{bean}"
filterEvent="keydown"
...
... >
...
...
<p:dataTable>
<h:form>
此jQuery可用于ID为is
的过滤器,但通过按给定的<p:commandButton>
更新此<p:dataTable>
时,它将停止运行.
This jQuery works fine for the filter whose id is is
but when this <p:dataTable>
is updated by pressing the given <p:commandButton>
, it stops functioning.
在AJAX更新<p:dataTable>
之后如何使此功能起作用?
How to make this function work after <p:dataTable>
is updated by AJAX?
引入了新的问题域:
此问题以及对PrimeFaces社区的相应答复论坛仍然不会导致以下问题域的解决方法/解决方案.
This question and corresponding replies on the PrimeFaces Community Forum still do not lead to a workaround/solution to the following problem domain.
如果按下了错误的键(即,非数字键,除了退格键,请删除 等),然后不必要地更新数据表,这会导致某些 要在完全完整的数据库上触发代价高昂的查询 ..
if a wrong key is hit (i.e a non-digit key, except backspace, delete etc) then, the data table is updated unnecessarily that causes some costly queries to be fired upon the database which is completely unnecessary and the data table must be prevented from being updated.
推荐答案
流程如下:
- 浏览器检索HTML输出.
- 浏览器基于HTML标记填充HTML DOM树.
- 完成后,浏览器将触发HTML DOM
ready
事件. - jQuery的
$(document).ready()
函数处理程序全部被调用. - 您可以通过ID在DOM中找到元素,并将
keydown
侦听器附加到该元素. - 在用户交互期间,将触发ajax请求,并使用ajax响应传递的新HTML元素更新HTML DOM树.
- 在其他元素中,具有
keydown
侦听器的元素正是从HTML DOM树中删除的,并被替换为没有任何keydown
侦听器的新元素.在ajax请求期间不会触发文档ready
事件.您准备好的处理程序永远不会被调用.keydown
侦听器永远不会重新连接.对于最终用户,它实际上确实似乎停止运行".
- Browser retrieves HTML output.
- Browser populates HTML DOM tree based on HTML markup.
- When finished, browser triggers HTML DOM
ready
event. - jQuery's
$(document).ready()
function handlers are all invoked. - Yours finds an element in DOM by ID and attaches a
keydown
listener to it. - During user interaction, an ajax request is fired and the HTML DOM tree is updated with new HTML elements delivered by the ajax response.
- Among others, exactly that element having the
keydown
listener is removed from HTML DOM tree and replaced by a fresh new element without anykeydown
listener. The documentready
event is not fired during ajax requests. Your ready handler is never re-invoked. Thekeydown
listener is never re-attached. To the enduser, it then indeed seemingly "stops functioning".
在这种特殊情况上的解决方案现在应该很明显:在完成ajax调用后,显式重新附加keydown
侦听器.最直接的方法是提取将keydown
侦听器附加到可重用函数中的工作,然后按以下步骤触发它:
The solution on this particular case should now be obvious: explicitly re-attach the keydown
listener on complete of ajax call. Most straightforward would be to extract the job of attaching the keydown
listener into a reusable function and fire it as follows:
function applyKeydownOnTableFilter() {
// ...
}
$(document).ready(applyKeydownOnTableFilter);
这样您就可以执行以下操作:
So that you can just do a:
<p:commandButton ... oncomplete="applyKeydownOnTableFilter()" />
但是,对于每个单个的ajax命令/侦听器重复此操作很繁琐,而且对维护也不是很友好.更好的方法是采用不同的方法:改用jQuery的 $.on()
.替换
But this is quite tedious to repeat for every single ajax command/listener and not very maintenance friendly. Better is to approach it differently: use jQuery's $.on()
instead. Replace
$(document).ready(function() {
$("#form\\:dataTable\\:id\\:filter").keydown(function(event) {
// ...
});
});
作者
$(document).on("keydown", "#form\\:dataTable\\:id\\:filter", function(event) {
// ...
});
这样,keydown
侦听器实际上并未附加到感兴趣的元素上.相反,借助JavaScript的事件冒泡功能,keydown事件最终将到达$(document)
—它在JSF ajax请求期间始终存在并且通常不会更改.一旦到达,将触发$(document).on()
,它将确定事件的来源并检查它是否与给定的选择器匹配,如果匹配,则调用该函数.所有这些都无需将keydown
侦听器附加到物理元素,因此对于在HTML DOM树中是否删除/替换该元素不敏感.
This way the keydown
listener isn't actually attached to the element of interest. Instead, thanks to the event bubbling feature of JavaScript, the keydown event will ultimately reach the $(document)
— which is always present and usually not changed during JSF ajax requests. Once reached, the $(document).on()
is triggered, which will then determine the source of the event and check it if matches the given selector and if so, then invoke the function. This all without the need to attach the keydown
listener to the physical element and thus not sensitive to whether the element is removed/replaced in the HTML DOM tree.
顺便说一句,您还看到HTML DOM树和JSF组件树之间有多少相似之处吗?
By the way, do you also see how much similarities there are between HTML DOM tree and JSF component tree?
这篇关于通过Ajax更新JSF组件后,JavaScript/jQuery事件侦听器不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!