Tuesday, December 17, 2013

Primefaces: capturing the target list item clicked

First of all, kudos to Hatem Alimam for his answer, who solved this problem.

Here's the problem.

I have a @ViewScoped managed bean with a p:pickList filtered by a p:selectMany component using a p:ajax update event.

Like this

<p:outputLabel for="siteFilter" value="Site Filter:" style="width:100px;"/>
<p:selectOneMenu converter="#{siteTypeConverter}" id="siteFilter" value="#{myMB.selectedSiteType}" style="width:200px;">              
   <f:selectItem itemLabel="Select Site Type" itemValue="#{null}" />
   <f:selectItems value="#{myMB.siteTypeFilterList}" var="st" itemLabel="#{st.name}" itemValue="#{st}" />
   <p:ajax update="sites" listener="#{myMB.handleSiteTypeFilterChange}" oncomplete="rebindClicks()"/>

<p:outputLabel for="sites" value="Sites:" style="width:100px;"/>
   itemValue="#{site}" /> 

The idea here is to trigger a new event when the user clicks on some pickList target list item.

So, as suggested by @Hatem, we have to bind the click event to each one of the target elements. Like this

   <p:remoteCommand name="updateCommand" action="#{myMB.updateAccounts}" update="accounts"/>
<h:outputScript library="js" name="pickListHack.js" />   

Notice that I had to add it AFTER the form.

and pickListHack.js is located at WebContent/resources/js/pickListHack.js

function rebindClicks() {
    xyzabc.jq.on('click','.ui-picklist-target li',function(){
        var item = $(this).attr('data-item-value');
        updateCommand([{name:'param', value:item}]);

$(document).ready(function() {

The trick here seems to be that, after the update event, the binds are lost, so we have to rebind them after the update. That's  why p:ajax has that oncomplete event.

Finally, when the user clicks on the element from the target list, we call the updateCommand, declared via p:remoteCommand.

Notice that the selected item is passed as a parameter called "param". We get this parameter back in the managed bean like this

public void updateAccounts(){
   String value = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("param");
   this.accounts = value;

In this case, the value is just the ID, because that's what my siteConverter does to the object.

public class SiteConverter implements Converter,Serializable{

    private static final long serialVersionUID = -194442504109002565L;

    private MyEJB myEJB;

    public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2)
            throws ConverterException {
        if (arg2 != null){
            Site s = myEJB.getSiteById(Long.parseLong(arg2));
            return s;
            return null;

    public String getAsString(FacesContext arg0, UIComponent arg1, Object arg2)
            throws ConverterException {
        if (arg2 != null){
            Site s = (Site)arg2;
            return String.valueOf(s.getId());
            return null;

No comments:

Post a Comment