PrimeFaces AutoComplete displays suggestions while the input is typing. AutoComplete features various options, multiple selections, customizable content and other cool effects. Let’s see how to run a quick example of it.
Set up your Primefaces project
Firstly, to kickstart your Primefaces application include the following dependencies in your project’s pom.xml:
<dependencies> <dependency> <groupId>jakarta.platform</groupId> <artifactId>jakarta.jakartaee-api</artifactId> <version>8.0.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.primefaces</groupId> <artifactId>primefaces</artifactId> <version>10.0.0</version> </dependency> </dependencies>
With that in place, we are ready to add your first Primefaces Chart.
Create a Primefaces Autocomplete Form
Firstly, we will add an index.html page which contains a textfield and a combobox featuring the autocomplete:
<!DOCTYPE html> <html xmlns="http://www.w3c.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:p="http://primefaces.org/ui"> <h:head /> <h:body> <h:form id="jsfexample"> <p:panelGrid columns="2"> <p:outputLabel value="Enter Country" for="@next" /> <p:autoComplete id="acSimple" value="#{autoCompleteBean.text1}" completeMethod="#{autoCompleteBean.completeText}" scrollHeight="250" /> <p:outputLabel value="Select Country" for="@next" /> <p:autoComplete id="dd" dropdown="true" value="#{autoCompleteBean.text2}" completeMethod="#{autoCompleteBean.completeText}" scrollHeight="250" /> </p:panelGrid> </h:form> </h:body> </html>
Let’s see in detail our HTML page:
- To enable autocomplete we have to set to use the autoComplete element with the attribute completeMethod on the field we want to enable auto-completion. The target Bean method will return a List of String objects
- By default a TextField will be used. By setting the attribute “dropdown” to “true” the field will be rendered as a ComboBox.
Additionally, please note the “@next” search expression used in the Label. This search expression finds the next JSF element in the same level of the JSF tree.
Done with the View, let’s code the AutoCompleteBean:
@Named @RequestScoped public class AutoCompleteBean { private String text1; private String text2; public List<String> completeText(String query) { String queryLowerCase = query.toLowerCase(); List<String> countryList = new ArrayList<>(); List<Country> countries = getCountries(); for (Country country : countries) { countryList.add(country.getName()); } return countryList.stream().filter(t -> t.toLowerCase().startsWith(queryLowerCase)).collect(Collectors.toList()); } private List<Country> getCountries() { List<Country> countries = new ArrayList<Country>(); Locale[] locales = Locale.getAvailableLocales(); for (Locale locale : locales) { try { String iso = locale.getISO3Country(); String code = locale.getCountry(); String name = locale.getDisplayCountry(); if (!"".equals(iso) && !"".equals(code) && !"".equals(name)) { countries.add(new Country(iso, code, name)); } } catch (MissingResourceException ex) { ex.printStackTrace(); } } return countries; } // Getters/ Setters omitted }
As you can see, the AutoComplete requires a target field (text1, text2) to store the Field data. Also, you need to produce a List of String objects. This is done in the completeText method.
The method getCountries collects the list of Country names from Java’s Locale class and stores them in a Java Bean named Country:
class Country { private String iso; private String code; public String name; Country(String iso, String code, String name) { this.iso = iso; this.code = code; this.name = name; } }
Running the example AutoComplete application
Once deployed, we can test our application.
Let’s start from the TextField. As you can see, by default, auto-complete will be triggered when you type the first character:
Likewise, the Autocomplete Combobox allows to type in text and select from the Combo:
Advanced configurations
So far we have showed a basic usage of the Autocomplete feature. It is however possible to customize the fields by setting extra attributes. Let’s see a few of them.
Minimum number of characters
You can define a minimum number of characters to be typed before the hint is displayed. For example, to request a minimum of 3 characters:
<p:autoComplete id="acMinLength" minQueryLength="3" value="#{autoCompleteBean.txt2}" completeMethod="#{autoCompleteBean.completeText}" effect="fade" scrollHeight="250"/>
Also, notice we have included as AutoComplete effect to “fade” when the suggestion is displayed.
Maximum number of elements
By default, 7 elelemts are displayed at once. You can change this default, for example, to 10 as follows:
<p:autoComplete id="acMaxResults" maxResults="10" value="#{autoCompleteBean.txt4}" completeMethod="#{autoCompleteBean.completeText}" scrollHeight="250"/>
Also, notice we have included as AutoComplete effect to “fade” when the suggestion is displayed.
Using a POJO to AutoComplete the Field
The default example uses a List of String objects to fill up the Autocomplete selection. It is also possible to use a POJO as source of data:
<p:autoComplete id="pojo" value="#{autoCompleteBean.country1}" completeMethod="#{autoCompleteBean.completeCountry}" var="country" itemLabel="#{country.name}" itemValue="#{country}" converter="#{countryConverter}" forceSelection="true" scrollHeight="250"/>
This requires some little changes in the AutoComplete Bean to return a List of POJOs:
public List<Country> completeCountry(String query) { String queryLowerCase = query.toLowerCase(); List<Country> countries = getCountries(); return countries.stream().filter(t -> t.getName().toLowerCase().contains(queryLowerCase)).collect(Collectors.toList()); }
Besides it, a FacesConverter (named “countryConverter“) needs to be registered. The value assigned to @FacesConverter is converter id which will be used at view level:
@Named @FacesConverter(value = "countryConverter", managed = true) public class CountryConverter implements Converter<Country> { @Inject private CountryService countryService; @Override public Country getAsObject(FacesContext context, UIComponent component, String value) { if (value != null && value.trim().length() > 0) { try { return countryService.getCountriesAsMap().get(Integer.parseInt(value)); } catch (NumberFormatException e) { throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Conversion Error", "Not a valid country.")); } } else { return null; } } @Override public String getAsString(FacesContext context, UIComponent component, Country value) { if (value != null) { return String.valueOf(value.getId()); } else { return null; } } }
Finally, it is worth mentioning that POJO objects can also retrieved from a remote endpoint. To do that, replace the attribute completeMethod with completeEndpoint:
<p:autoComplete id="pojoRest" widgetVar="countryPojoRest" value="#{autoCompleteBean.country5}" var="country" itemLabel="#{country.displayName}" itemValue="#{country}" converter="#{countryConverter}" completeEndpoint="#{request.contextPath}/rest/country/autocomplete" forceSelection="true" emptyMessage="sorry, no suggestions" moreText="more items available" scrollHeight="250"/>
Within your remote Endpoint, the List of POJO objects will be returned:
@GET @Path("itemList") @Produces("application/json") public List<Country> getCountries() { List<Country> countries = new ArrayList<Country>(); Locale[] locales = Locale.getAvailableLocales(); for (Locale locale : locales) { try { String iso = locale.getISO3Country(); String code = locale.getCountry(); String name = locale.getDisplayCountry(); if (!"".equals(iso) && !"".equals(code) && !"".equals(name)) { countries.add(new Country(iso, code, name)); } } catch (MissingResourceException ex) { ex.printStackTrace(); } } return countries; }
Conclusion
We have covered how to use the autocomplete feature in PrimeFaces applications to simplify form edting.
Source code for this article: https://github.com/fmarchioni/mastertheboss/tree/master/web/primefaces/autocomplete