Search code examples
javajsfprimefacesomnifaces

Primefaces picklist target and source values do not change


My primefaces pickList source and target values do not change, I have followed the example in primefaces showcase and also looked at several posts here but still am not able to solve the problem. I am using a list from the database to populate the source as follows:

private DualListModel<Course> courseModel;
public CourseBean() {
    List<Course> target = new ArrayList<Course>();
    List<Course> source = new ArrayList<Course>();
    courseModel = new DualListModel<Course>(source, target);
}
...
//this DualListModel getter also populates the source with values from db
public DualListModel<Course> getCourseModel() {
    courseModel.setSource(getCourseList());
    return courseModel;
}

My converter is

import org.omnifaces.converter.SelectItemsConverter;

@FacesConverter("courseConverter")
public class CourseConverter extends SelectItemsConverter {
@Override
public String getAsString(FacesContext context, UIComponent component,
        Object value) {
    Integer id = (value instanceof Course) ? ((Course) value).getId()
            : null;
    return (id != null) ? String.valueOf(id) : null;
}
@Override
public Object getAsObject(FacesContext arg0, UIComponent arg1, String value) {
    Course course = new Course();
    course.setId(Integer.parseInt(value));
    return course;
}
}

and finally my xhtml page is:

<h:form>
    <p:pickList id="coursesOffered"
        value="#{courseView.courseModel}" var="course"
        itemValue="#{course}" itemLabel="#{course.courseTitle}"
        converter="courseConverter" showSourceFilter="true"
        showTargetFilter="true" filterMatchMode="contains">

        <f:facet name="targetCaption">Selected</f:facet>
        <f:facet name="sourceCaption">All Courses</f:facet>

        <p:ajax event="transfer" listener="#{courseView.onTransfer}" />

        <p:column style="width:10%">  
        #{course.courseCode}:
    </p:column>
        <p:column style="width:90%">  
       #{course.courseTitle}  
    </p:column>

    </p:pickList>

    <p:commandButton id="pojoSubmit" value="Submit"
        update="displayPlayers" oncomplete="playerDialog.show()"
        style="margin-top:5px" />

    <p:dialog showEffect="fade" hideEffect="fade" widgetVar="playerDialog">
        <h:panelGrid id="displayPlayers" columns="2">

            <h:outputText value="Source: " style="font-weight:bold" />
            <ui:repeat value="#{courseView.courseModel.source}"
                var="course">
                <h:outputText value="#{course.courseTitle}"
                    style="margin-right:5px" />
            </ui:repeat>

            <h:outputText value="Target: " style="font-weight:bold" />
            <ui:repeat value="#{courseView.courseModel.target}"
                var="course">
                <h:outputText value="#{course.courseTitle}"
                    style="margin-right:5px" />
            </ui:repeat>

        </h:panelGrid>
    </p:dialog>
</h:form>

The pickList is displayed correctly with source populated with values from database, however, upon clicking the button, the dialog just displays the original source list values and an empty target list even after transferring items on the interface. What am I missing?


Solution

  • I see some problems with your code. In the getter, you are reconstructing the DualList from the database, reseting any changes you've done so far.

    try making you getter something like this:

    public DualListModel<Course> getCourseModel() {
        return this.courseModel;
    }
    

    Construct and load your list from the database in a method annotated @PostConstruct rather than in the constructor+getter.

    public CourseBean() {}
    
    @PostConstruct
    public void init() {
        List<Course> target = new ArrayList<Course>();
        courseModel.setSource(getCourseList());
        courseModel = new DualListModel<Course>(source, target);
    }
    

    Also annotate your bean @ViewScoped, so you dont construct a new bean with empty target-list on every request

    @ManagedBean(name="courseView")
    @ViewScoped
    public class CourseBean {
    
    }
    

    Finally you also need a setter:

    public void setCourseModel(DualListModel<Course> courseModel) {
        this.courseModel = courseModel;
    }
    

    I have not really looked into the converter, when I did a picklist lasttime i took the converter included in primefaces showcase (Never tried the omnifaces one). Here is a link to the source: http://code.google.com/p/ind/source/browse/indicadorCensoJSF/src/ve/gob/ine/censo/beans/convert/PrimeFacesPickListConverter.java?spec=svn154&r=154