PrincAm
PrincAm

Reputation: 327

Primefaces SelectOneMenu doesn't update default value

I have a datatable with a single selection. After selection of a row and pressing button, dialog with input texts and select one menus will open. Input texts and one menus should contain data of selected row. In general, it is a dialog for editing records in datatable. But select one menus in dialog will not change default value based on selected row. It is working with <h:selectOneMenu> but not with extended from Primefaces <p:selectOneMenu>. What I am doing wrong? I am using Primefaces 5.0 and JSF 2.1.

XHTML:

<h:form id="form">
    <p:dataTable 
        id="datatable"
        var="spec" 
        value="#{selectionRowAction.specimensBO.list}"
        selection="#{selectionRowAction.selectedSpecimen}"
        selectionMode="single"
        rowKey="#{spec.id}"
        resizableColumns="true">

        <f:facet name="header">
            <p:commandButton id="editButton"
                             process="datatable"
                             update=":form:editPanel" 
                             icon="ui-icon-pencil" 
                             oncomplete="PF('dlg').show()"/>
        </f:facet>  
        <p:column headerText="ID" >
            <h:outputText value="#{spec.subjectIdNumber}" />
        </p:column>
        <p:column headerText="Type" >
            <h:outputText value="#{spec.specimenType.displayText}" />
        </p:column>
    </p:dataTable>

    <p:dialog widgetVar="dlg" >
        <p:outputPanel id="editPanel" >
            <p:panelGrid  columns="2">                  
                <h:outputText value="ID: "/>
                <p:inputText 
                    value="#{selectionRowAction.selectedSpecimen.subjectIdNumber}"/>            
                <h:outputText value="Type: " />
                <p:selectOneMenu 
                    value="#{selectionRowAction.selectedSpecimen.specimenType}" 
                    converter="#{specimenTypeConverter}">
                    <f:selectItem itemLabel="Select One"/>           
                    <f:selectItems value="#{basicSelectionsBO.specimenTypes}" 
                                   var="type" 
                                   itemLabel="#{type.displayText}" 
                                   itemValue="#{type}"/>
                </p:selectOneMenu>
            </p:panelGrid>  
        </p:outputPanel>
    </p:dialog>
</h:form>

Upvotes: 0

Views: 4359

Answers (2)

ThomasH
ThomasH

Reputation: 1

Another possible cause could be (as mentioned in other posts - I'm only including it here to help with others who haven't yet found it) the list of objects that the selectOneMenu is displaying being reloaded during/immediately after the RowEditEvent listener is called.

I had the same behaviors as described by the OP (PrincAm), and refactored endlessly the equals() & hashCode() methods (even writing as many unit test cases as I could think of to prove them out); the equals() & hashCode() methods were correct, but the behaviors still persisted. I had even refactored the equals() method to always return true or always return false, and the selectOneMenu value would be set to the first menu option or the last menu option, respectively.

Only after finding a brief mention of the possibility of reloading the values did I go back and look at how/when that collection was being loaded; I discovered that during the action method which saved the datatable's row, I would call a refresh() method, which reloaded the collection of selectable values. Once I refactored my code to NOT reload that list, the selectOneMenu would keep the correct value selected as intended.

Again, just adding another possible solution to this VERY irritating and somewhat obscure issue. Kudos to both PrincAm & JaqenH'ghar for their postings as valuable resources to others.

Upvotes: 0

Jaqen H&#39;ghar
Jaqen H&#39;ghar

Reputation: 4345

When SelectOneMenu's and similar components don't work as expected one should check the converter and make sure there are equals() and hashCode() methods on the entities/pojos. In this case you are missing the two methods. A simple implementation copied from BalusC's post is:

@Override
public boolean equals(Object other) {
    return (other instanceof EntityType) && (id != null)
        ? id.equals(((EntityType) other).id)
        : (other == this);
}

@Override
public int hashCode() {
    return (id != null)
        ? (this.getClass().hashCode() + id.hashCode())
        : super.hashCode();
}

If id can be null one needs to use more fields in these methods. One can also use the Apache Commons/Lang HashCodeBuilder and EqualsBuilder as explained in the answer here.

To verify the framework actually calls these methods you can try to just return true; in the equals method, which should always make the last option in the SelectOneMenu selected no matter the value in the bean. With return false; it will be the first option.

Upvotes: 3

Related Questions