0

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>
PrincAm
  • 317
  • 5
  • 17
  • 1
    Do you have equals() and hashCode() on the class SpecimenType ? – Jaqen H'ghar Jul 12 '14 at 17:01
  • @JaqenH'ghar Thanks for your response. SpecimenType is a data model class containing properties with getters and setters. Should I override `equals()` and `hashCode()` methods? – PrincAm Jul 13 '14 at 09:43
  • I am not sure but I think its a requirement.. when selectmenus gives problems its typically caused by either this or the converter. For implementation see for example BalusC's answer here: http://stackoverflow.com/questions/10726716/primefaces-selectonemenu-doesnt-working-when-it-should – Jaqen H'ghar Jul 13 '14 at 10:01
  • @JaqenH'ghar Amazing, it's working. Could you please answer my question? I would like to accept your solution. – PrincAm Jul 13 '14 at 10:35

2 Answers2

3

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.

Community
  • 1
  • 1
Jaqen H'ghar
  • 4,305
  • 2
  • 14
  • 26
0

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.

ThomasH
  • 1
  • 1