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();
}
}
});
});
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"/>
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>
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.
How to make this function work after <p:dataTable>
is updated by AJAX?
A new problem domain introduced:
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.
The flow is as follows:
ready
event.$(document).ready()
function handlers are all invoked.keydown
listener to it.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".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 thekeydown
listener into a reusable function and fire it as follows:So that you can just do a:
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. Replaceby
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 thekeydown
listener to the physical element and thus not sensitive to whether the element is removed/replaced in the HTML DOM tree.See also:
By the way, do you also see how much similarities there are between HTML DOM tree and JSF component tree?