Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Primefaces, autocomplete, multiple mode. How to avoid selecting same item twice?

Tags:

jsf

primefaces

I know that I can't do it in Primefaces directly, I understand that I have to do it in Converter but don't really know at which stage and how? And what exactly should I check? Maybe to do this I need to wedge in a lifecycle of JSF? For example after p:Autocomplete add item to list in a "Apply request values phase" I should check if there duplicate item and remove it before "Update model values phase", if I understand JSF lifecycle in a right way? Is it possible at all? Thank you in advance.

like image 618
Anatoly Avatar asked Jul 30 '14 20:07

Anatoly


2 Answers

It's possible, what you have to do is to keep the model up to date for each of user's selection/unselection. That's done using a <p:ajax /> tag into the <p:autoComplete />, so the List of selected items will be updated in the back-end. Later on, when user asks for other query, mind about that List.

Check out this SSCCE with a List of String values (you might choose to use a Converter or not for your custom classes, but that's not related at all with your question):

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:p="http://primefaces.org/ui">
<h:head />
<h:body>
    <h:form>
        <p:outputLabel value="Multiple:" />
        <p:autoComplete multiple="true"
            value="#{autoCompleteBean.selectedItems}"
            completeMethod="#{autoCompleteBean.completeItem}" var="it"
            itemLabel="#{it}" itemValue="#{it}" forceSelection="true">
            <p:ajax event="itemSelect" />
            <p:ajax event="itemUnselect" />
            <p:column>
                <h:outputText value="#{it}" />
            </p:column>
        </p:autoComplete>
    </h:form>
</h:body>
</html>
@ManagedBean
@ViewScoped
public class AutoCompleteBean {

    /**
     * The items currently available for selection
     */
    private List<String> items = new ArrayList<String>();

    /**
     * Current selected items
     */
    private List<String> selectedItems = new ArrayList<String>();

    /**
     * All the items available in the application
     */
    private List<String> allItems = new ArrayList<String>();

    /**
     * Create a hardcoded set of items and add all of them for selection
     */
    public AutoCompleteBean() {
        allItems.add("item1");
        allItems.add("item2");
        allItems.add("item3");
        allItems.add("item4");
        items.addAll(allItems);
    }

    /**
     * Check the current user query for selection. If it fits any of the items
     * of the system and it's not already selected, add it to the filtered List
     * 
     * @param query
     * @return
     */
    public List<String> completeItem(String query) {
        List<String> filteredList = new ArrayList<String>();
        for (String item : allItems) {
            if (item.startsWith(query) && !selectedItems.contains(item)) {
                filteredList.add(item);
            }
        }
        return filteredList;
    }

    public List<String> getItems() {
        return items;
    }

    public List<String> getSelectedItems() {
        return selectedItems;
    }

    public void setSelectedItems(List<String> selectedItems) {
        this.selectedItems = selectedItems;
    }

}
like image 118
Xtreme Biker Avatar answered Nov 15 '22 09:11

Xtreme Biker


Current version of PrimeFaces (6.2.x) has an "unique" attribute for this matter.

like image 24
ChRoNoN Avatar answered Nov 15 '22 10:11

ChRoNoN