Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using PrimeFaces <p:ajax>, fire up Ajax in inputText only on keystrokes that change the field

I am using PrimeFaces and have a p:inputText field where I need to update some components on the view based on the latest keystroke inside that p:inputText. Here's the code:

<p:inputText value="#{customerLController.surnameFilterConstraint}"
             id="surnamefilterfield">
    <p:ajax event="keyup" 
            update=":custForm:custDataTable"
            listener="#{customerLController.focusSurname}"
            oncomplete="primeFacesId('surnamefilterfield')"/>
</p:inputText>

The thing is, the above code fires up Ajax even in the case of arrow keystrokes (which I would rather avoid given the costly update). Ideally I would like a different version of p:ajax event="change" with the qualification that change is pronounced on keystrokes and not when the user hits Enter (which is what happens now).

If the p:ajax component doesn't allow a way to filter out certain keyup events, then I gather that the only (?) alternative would be to call JavaScript on the client side and then implement the Ajax call in Javascript but then I would forsake the convenience of using the PrimeFaces p:ajax component, wouldn't I?

like image 664
Marcus Junius Brutus Avatar asked Jul 27 '12 12:07

Marcus Junius Brutus


1 Answers

Since JSF 2.2, I am using elegant way to solve this issue.

Solution is based on combination of p:remoteCommand (as pointed out in one of comments) and namespace http://xmlns.jcp.org/jsf/passthrough which allows you to define native HTML event attributes in JSF components.

In this case it would be:

  1. First add new namespace to your page

    xmlns:pt="http://xmlns.jcp.org/jsf/passthrough"
    
  2. Modify p:inputText and add p:remoteCommand

    <p:inputText id="surnamefilterfield" 
              value="#{customerLController.surnameFilterConstraint}" 
              pt:onkeyup="onKeyUpFilterKeyCode(event)"/>
    <p:remoteCommand delay="300" name="onFilteredKeyUp" 
                  actionListener="#{customerLController.focusSurname}" /> 
    
  3. add JavaScript function

       function onKeyUpFilterKeyCode(event){
            var keyCode=event.keyCode;
            console.log("Key code = " + keyCode);
            //if key is not ENTER and not cursor/arrow keys
            if ((keyCode != 13) && !((keyCode >= 37) && keyCode <= 40)){
                //call remoteCommand
                onFilteredKeyUp();
            }
        }
    

(since this JS function contains "special" XML chars follow BalusC recommendations about how to add it to JSF/XML web page)

The advantage of this approach is that you can ajaxify any native HTML event supported by component (and WEB browser) while still using JSF/Primefaces components and "JSF way" of creating WEB pages.

like image 65
Dusan Kovacevic Avatar answered Oct 05 '22 11:10

Dusan Kovacevic