JSF2 search box

15,034

First step, If you are using a Java EE 6 compatible container (like GlassFish V3, Resin 4, JBoss AS 6 or 7, etc) and you have put something like commons-el.jar in your WEB-INF, remove it. This isn't needed and will only do harm.

I want a search field with no button (just type and hit enter and give the result)

In that case you also don't need the command button, but could go with something like this:

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
>
    <h:head/>

    <h:body>        

        <h:form>
            <h:inputText id="search" value="#{bookBean.searchString}" 
                onkeypress="if (event.keyCode == 13) {onchange(event); return false;}"
                onchange="return event.keyCode !== undefined" 
            >
                <f:ajax listener="#{bookBean.updateBook}" render="output" />
            </h:inputText>

            <h2>
                <h:outputText id="output" value="#{bookBean.book}"/>
            </h2>
        </h:form>

    </h:body>
</html>

With the bookBean defined as:

@ViewScoped
@ManagedBean
public class BookBean {

    private Map<String, String> exampleData = new HashMap<String, String>() {{ 
        put("dune", "The Dune Book"); 
        put("lotr", "The Lord of the Rings Book");
    }};

    private String searchString; 
    private String book;

    public void updateBook(AjaxBehaviorEvent event) {
        book = exampleData.get(searchString);
    }

    public String getSearchString() {
        return searchString;
    }

    public void setSearchString(String searchString) {
        this.searchString = searchString;
    }

    public String getBook() {
        return book;
    }

}

In the Facelet, note the importance of the h:head element. Without it JSF does not know where to insert the required script for AJAX support in your response.

In the example, the default onchange method that JSF generates when the f:ajax client behavior is added to so-called EditableValueHolders is called whenever the user presses enter. The listener attribute causes a method to be called on the AJAX event. Since searchString is already bound to a property of the backing bean, you don't have to provide it as argument to the listener method.

A small disadvantage of this method is that the AJAX call will also be invoked when you change the value in the search field and simply click outside it.

Update

Adding an onchange handler to h:inputText fixed the above mentioned problem. This is automatically chained by JSF with the AJAX code from the client behavior. If it returns false, the chain is aborted and thus the AJAX call doesn't take place.

The handler onchange="return event.keyCode !== undefined" will return false if the handler is triggered by the real change event; the event object will then not have the keyCode property.

Share:
15,034
hcpeter
Author by

hcpeter

Updated on June 14, 2022

Comments

  • hcpeter
    hcpeter almost 2 years

    I develop a little app in javaee6 and jsf2. I want a search field with no button (just type and hit enter and give the result). I have a search method in a bean:

    public Book searchByTitle(String title) {
        this.book = bookFacade.searchByTitle(title);
        return book;
    }
    

    I want to call this method via jsf page (with parameter? Is it possible?), so I try to do this:

        <h:form>
            <h:inputText id="search" value="#{bookBean.searchString}"></h:inputText>
            <h:commandButton value="Search by title" action="#{bookBean.searchByTitle}">
                <f:ajax execute="search" render="output"></f:ajax>
            </h:commandButton>
            <h2><h:outputText id="output" value="#{bookBean.book.title}"></h:outputText>
            </h2>
        </h:form>
    

    But it isn't work. What the proper way to do a search field in a jsf2 xhtml page?

    Edit: I tried to call the searchByTitle function with/without parameter.

    Thanks in advance!