One of the robust things that could consider when you come for adapting the Primefaces implementation is the Client Side API, this API provides you a full functional facility to control the component that you want to use. AutoComplete isn’t an exception of this role, it’s also supported by a rich amount of services that could be invoked through the Java Script.
Before accessing the AutoComplete component, you have to define what’s already defined before and named as WidgetVar. WidgetVar is a Primefaces concept, at which the JavaScript code works.
- Read : PrimeFaces Tutorials
You’ve already seen the invoking of AutoComplete behaviors by the user interaction with the component itself, so behavior like close can be happened once the user has unfocused the component while the suggestions are shown. And behavior like search can be happened once the user has typed a text inside the component. All of these behaviors can be achieved through an API provided for the component itself in addition for other behaviors such as activate the search and deactivate it.
This tutorial explains how to implement AutoComplete with the help of Client Side API in PrimeFaces.
1. Client Side API for AutoComplete
Primefaces provides you the following api that could be invoked via of JavaScript.
- close: Hides suggested items menu
- disable: Disables the input field
- enable: Enables the input field
- search: Initiates a search with given value
- activate: Activates search behavior
- deactivate: De Activates search behavior
2. The View
index.xhtml
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:p="http://primefaces.org/ui"> <h:head> <script name="jquery/jquery.js" library="primefaces"></script> <script> function close(){ PF('autoVar').close(); } function disable(){ autoVar.disable(); } function enable(){ PF('autoVar').enable(); } function deactivate(){ autoVar.deactivate(); } function activate(){ PF('autoVar').activate(); } function search(){ PF('autoVar').search('Ol'); } </script> </h:head> <f:view afterPhase="#{autoComplete.phaseListener}"> <h:form prependId="false"> <h1>JavaBeat Primefaces Example</h1> <h2>Primefaces - AutoComplete + Client Side API</h2> <h:outputText value="Enter name of the player you wish to see statistics for :"/> #{' '} <p:autoComplete widgetVar="autoVar" id="auto" value="#{autoComplete.players}" completeMethod="#{autoComplete.complete}" var="player" itemValue="#{player}" itemLabel="#{player.playerName}" converter="#{playerConverter}" multiple="true"> <f:facet name="itemtip"> <h:panelGrid> <f:facet name="header"> <h:graphicImage value="/resources/images/#{player.playerImage}"></h:graphicImage> </f:facet> <h:outputText value="Name: "/> <h:outputText value="#{player.playerName}"/> <h:outputText value="Position: "/> <h:outputText value="#{player.playerPosition}"/> </h:panelGrid> </f:facet> <p:ajax event="itemSelect" listener="#{autoComplete.handleSelect}" update="msg"></p:ajax> <p:ajax event="itemUnselect" listener="#{autoComplete.handleUnSelect}" update="msg"></p:ajax> </p:autoComplete> <br/> <p:messages id="msg"/> <br/><br/> <br/><br/> <h:panelGrid columns="2" cellpadding="5px;" border="1"> <f:facet name="header"> <h2>Java Script Actions</h2> </f:facet> <h:commandLink value="Search About Players Starting With Ol" onclick="search();return false;" title="This action will search about players their names starting with Ol"/> <h:commandLink value="Close Suggestions" onclick="close();return false;" title="This action will close the suggestions"/> <h:commandLink value="Activate Search Behavior" onclick="activate();return false;" title="This action will activate the search by using client side api"/> <h:commandLink value="Deactivate Search Behavior" onclick="deactivate();return false;" title="This action will de activate the search by using client side api"/> <h:commandLink value="Disable AutoComplete" onclick="disable();return false;" title="This action will disable the input"/> <h:commandLink value="Enable AutoComplete" onclick="enable();return false;" title="This action will enable the input"/> </h:panelGrid> </h:form> </f:view> </html>
3. Managed Bean
AutoComplete.java
package net.javabeat.primefaces; import java.util.List; import javax.faces.application.FacesMessage; import javax.faces.bean.ManagedBean; import javax.faces.bean.ManagedProperty; import javax.faces.bean.SessionScoped; import javax.faces.context.FacesContext; import javax.faces.event.PhaseEvent; import net.javabeat.primefaces.data.Player; import net.javabeat.primefaces.util.PlayerDataSource; import org.primefaces.event.SelectEvent; import org.primefaces.event.UnselectEvent; @ManagedBean @SessionScoped public class AutoComplete { @ManagedProperty("#{playerDataSource}") private PlayerDataSource ds; private List<Player> players; public AutoComplete (){ } public List<Player> complete(String query){ // Assumed Datasource return ds.queryByName(query); } public List<Player> getPlayers() { return players; } public void setPlayers(List<Player> players) { this.players = players; } public PlayerDataSource getDs() { return ds; } public void setDs(PlayerDataSource ds) { this.ds = ds; } public void handleSelect(SelectEvent e){ Player p = (Player)e.getObject(); FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Add Player :: Player Info: ID :: "+ p.getPlayerId() + " :: Name :: "+p.getPlayerName(),"")); } public void handleUnSelect(UnselectEvent e){ Player p = (Player)e.getObject(); FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Remove Player :: Player Info: ID :: "+ p.getPlayerId() + " :: Name :: "+p.getPlayerName(),"")); } public void phaseListener(PhaseEvent e){ List<FacesMessage> messages = e.getFacesContext().getMessageList(); System.out.println(messages.size()); } }
4. The Datasource
PlayerDataSource.java
package net.javabeat.primefaces.util; import java.util.ArrayList; import java.util.List; import javax.faces.bean.ManagedBean; import javax.faces.bean.SessionScoped; import net.javabeat.primefaces.data.Player; @ManagedBean @SessionScoped public class PlayerDataSource { public List<Player> players = new ArrayList<Player>(); public PlayerDataSource(){ // Assumed Player Player player = new Player(); player.setPlayerId("1"); player.setPlayerName("Anderias Muller"); player.setPlayerPosition("CF"); player.setPlayerAge("24"); player.setPlayerImage("am.png"); // Add Player players.add(player); // Assumed Player player = new Player(); player.setPlayerId("2"); player.setPlayerName("Olaf Thon"); player.setPlayerPosition("CM"); player.setPlayerAge("29"); player.setPlayerImage("ot.png"); // Add Player players.add(player); // Assumed Player player = new Player(); player.setPlayerId("3"); player.setPlayerName("Oliver Khan"); player.setPlayerPosition("GK"); player.setPlayerAge("31"); player.setPlayerImage("ok.png"); // Add Player players.add(player); } public List<Player> getPlayers() { return players; } public void setPlayers(List<Player> players) { this.players = players; } public List<Player> queryByName(String name){ // Assumed search using the startsWith List<Player> queried = new ArrayList<Player>(); for(Player player: this.players){ if(player.getPlayerName().startsWith(name)){ queried.add(player); } } return queried; } }
5. The Converter
PlayerConverter.java
package net.javabeat.primefaces.converter; import javax.faces.bean.ManagedBean; import javax.faces.bean.ManagedProperty; import javax.faces.bean.RequestScoped; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import javax.faces.convert.Converter; import javax.faces.convert.FacesConverter; import net.javabeat.primefaces.data.Player; import net.javabeat.primefaces.util.PlayerDataSource; //To be considered by the JavaServer Faces As Managed Bean // & Make the converter Eligible for use @ManagedProperty @ManagedBean @RequestScoped @FacesConverter public class PlayerConverter implements Converter{ @ManagedProperty(value="#{playerDataSource}") private PlayerDataSource ds; public PlayerDataSource getDs() { return ds; } public void setDs(PlayerDataSource ds) { this.ds = ds; } @Override public Object getAsObject(FacesContext context, UIComponent component,String value) { for(Player p : ds.getPlayers()){ if(p.getPlayerId().equals(value)){ return p; } } return null; } @Override public String getAsString(FacesContext context, UIComponent component,Object value) { if(value instanceof Player){ Player player = (Player)value; return player.getPlayerId(); } return ""; } }
6. Player Pojo
Player.java
package net.javabeat.primefaces.data; public class Player { private String playerId; private String playerName; private String playerPosition; private String playerAge; private String playerImage; public String getPlayerId() { return playerId; } public void setPlayerId(String playerId) { this.playerId = playerId; } public String getPlayerName() { return playerName; } public void setPlayerName(String playerName) { this.playerName = playerName; } public String getPlayerPosition() { return playerPosition; } public void setPlayerPosition(String playerPosition) { this.playerPosition = playerPosition; } public String getPlayerAge() { return playerAge; } public void setPlayerAge(String playerAge) { this.playerAge = playerAge; } public String getPlayerImage() { return playerImage; } public void setPlayerImage(String playerImage) { this.playerImage = playerImage; } public boolean equals(Object obj){ if(obj instanceof Player){ Player player = (Player)obj; if(this.playerId.equals(player.getPlayerId())){ return true; } } return false; } public int hashCode(){ return this.playerId.hashCode(); } }
7. PrimeFaces AutoComplete + POJO + Client Side API Demo
Note the following points when you comes to run the demo:
- The search link should do search on all players that have names starting with Ol, cause the search function provide this value as a parameter.
- Close suggestions, should hide the suggestions only, with capability of showing it again.
- Deactivate search will prevent you from doing a search through using client side API.
- Activate search will allow you to do a search via client side API.
- Disable, should disable the input. so the user couldn’t be capable to enter any text within it.
- Enable, will enable the input again for accepting the user inputs.