txapeldot
txapeldot

Reputation: 93

Iterate suggestions list of PrimeFaces Autocomplete element within getAsObject() method

I have a p:autoComplete PF element to deal with a POJO-suggestions list for which I've created a Converter class to map POJOs into Strings and vice versa.

<p:autoComplete value="#{bean.pojoTargetList}" completeMethod="#{bean.getPOJOFilteredList}" var="pojo" itemLabel="#{pojo.name}"
itemValue="#{pojo}" converter="pojoConverter" />

The thing is I know how to procceed to map from a POJO to a String (getAsString()method) but not how to do to map from a String to a POJO (getAsObject()method).

@FacesConverter("pojoConverter")
public class POJOConverter implements Converter {

@Override
public Object getAsObject(FacesContext arg0, UIComponent uiComponent, String value) {
    // ?        
    return pojo;
}

@Override
public String getAsString(FacesContext arg0, UIComponent uiComponent, Object assetTag) {
    String _return = null;
    ...
    return _return;
}

Maybe I'm wrong but my understanding is that the uiComponent param of the getAsObject() method is a reference to the p:autoComplete PF element. If so, I could have access to the POJO-suggestions list. Therefore, I could iterate on it and and find the POJO object matching the value param.

I'd really appreciate if someone could explain how can I access the pojo suggesion list of the p:autocomplete element from the getAsObject()method.

UPDATE: Maybe I'm wrong but my understanding is that the uiComponent param of the getAsObject() method is a reference to the p:autoComplete PF element. If so, I could have access to bean.getPOJOFilteredList. Therefore, I could iterate on bean.getPOJOFilteredList and find the POJO object matching the value param.

Upvotes: 1

Views: 529

Answers (2)

bill tsi
bill tsi

Reputation: 51

You can have access to the suggestion list and iterate it, by getting the completeMethod from the component and invoke it like this:

MethodExpression method = ((AutoComplete) component).getCompleteMethod();
List<Object> items = (List) method.invoke(facesContext.getELContext(), null);
for(Object item : items)
    if(item.equals(value))
       return item;

Now in your completeMethod you can add

public List<Object> yourAutoCompleteMethod(String query){
    if(query == null) return list;
    else
       //fetch your data//
       return list;
 }

so the converter will immediately get the list that you previously calculated. By this way you have access to the suggestion list, without any injections or other mapping. It is plug and play.

Upvotes: 1

Jens Piegsa
Jens Piegsa

Reputation: 7505

Yes, a Converter needs access to the objects he is expected to return. An implementation may look like this:

@FacesConverter("userConverter")
public class UserConverter implements Converter {

    @Inject
    UserDirectory userDirectory;

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String uid) {
        return uid == null || uid.isEmpty() ? null : userDirectory.findByUid(uid);
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object user) {
        final String uid = user instanceof User ? ((User) user).getUid() : null;
        return StringUtils.defaultIfEmpty(uid, "");
    }
}

The auto-complete method must be implemented independently and should return a list of the particular objects based on some partial input, being case-insensitive, etc.:

public List<User> autoCompleteUser(String queryString) {

    // implement custom retrieval / filter logic

    return filteredUsers;
}

Upvotes: 0

Related Questions