JavaScript / jQuery event listeners do not work after the JSF component is updated via Ajax

I execute the following jQuery function in <p:dataTable> filter (whose id is id ), which allows users to enter only numbers 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, for example,

 <h:outputScript library="default" name="js/digit_only_textfield.js"/> 

The XHTML page is as follows.

 <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 with the identifier is , but when this <p:dataTable> updated by pressing this <p:commandButton> , it stops working.

How to make this function work after <p:dataTable> updated with AJAX?


A new problem domain has been introduced:

This question and the corresponding answers in the PrimeFaces community forum still do not lead to a workaround / solution to the next problem domain.

if the wrong key is damaged (i.e., a non-digital key, with the exception of backspace, delete, etc.), then the data table is updated unnecessarily, which causes some costly queries to be launched in a database that is completely unnecessary , and the table data should be prevented due to updates .

+7
javascript jquery jsf primefaces
source share
1 answer

The stream is as follows:

  • The browser retrieves the HTML output.
  • The browser populates the HTML DOM tree based on HTML markup.
  • Upon completion, the browser fires the HTML DOM ready event.
  • jQuery $(document).ready() all function handlers.
  • Your locates the element in the DOM by ID and attaches a keydown listener to it.
  • During user interaction, an ajax request is triggered, and the HTML DOM tree is updated with new HTML elements passed in using the ajax response.
  • In particular, it is this element with the keydown listener that is removed from the HTML DOM tree and replaced with a new new element without the keydown . The ready event does not fire during ajax requests. Your ready handler will never be recalled. The keydown listener never joins. For the end user, he then apparently "ceases to function."

The solution in this particular case should now be obvious: explicitly reattach the keydown listener to end the ajax call. The simplest would be to extract the task of attaching the keydown listener to the reusable function and run it as follows:

 function applyKeydownOnTableFilter() { // ... } $(document).ready(applyKeydownOnTableFilter); 

So you can just do:

 <p:commandButton ... oncomplete="applyKeydownOnTableFilter()" /> 

But it is rather tedious to repeat for each individual ajax command / listener and not very service friendly. It's better to approach it differently: use jQuery $.on() instead. Replace

 $(document).ready(function() { $("#form\\:dataTable\\:id\\:filter").keydown(function(event) { // ... }); }); 

by

 $(document).on("keydown", "#form\\:dataTable\\:id\\:filter", function(event) { // ... }); 

Thus, the keydown listener is keydown actually attached to the element of interest. Instead, thanks to the JavaScript event buffering function, the keydown event will eventually reach $(document) - which is always present and usually does not change during ajax JSF requests. After that, $(document).on() , which will then determine the source of the event and check it if it matches the given selector, and if so, then call the function. This is all without having to attach the keydown listener to the physical element and, therefore, is insensitive to whether the element in the HTML DOM tree is being deleted or deleted.

See also:

  • JSF / PrimeFaces ajax updates jQuery function breaks for event listener

By the way, you also see how much in common is there between the HTML DOM tree and the JSF component tree?

+6
source share

All Articles