Primefaces SelectOneMenu не обновляет значение по умолчанию

У меня есть дата с одним выбором. После выбора строки и нажатия кнопки откроется диалоговое окно с вводом текста и выбором одного меню. Входные тексты и одно меню должны содержать данные выбранной строки. В общем, это диалог для редактирования записей в datatable. Но выбор одного меню в диалоговом окне не изменит значения по умолчанию на основе выбранной строки. Работает с <h:selectOneMenu> но не с расширенными от Primefaces <p:selectOneMenu>, Что я делаю не так? Я использую Primefaces 5.0 и 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>

2 ответа

Решение

Когда SelectOneMenu и подобные компоненты не работают должным образом, следует проверить конвертер и убедиться, что в entity / pojos есть методы equals() и hashCode(). В этом случае вам не хватает двух методов. Простая реализация, скопированная из поста BalusC:

@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();
}

Если id может быть нулевым, нужно использовать больше полей в этих методах. Можно также использовать Apache Commons/Lang HashCodeBuilder и EqualsBuilder, как описано в ответе здесь.

Чтобы убедиться, что фреймворк на самом деле вызывает эти методы, вы можете попробовать просто return true; в методе equals, который всегда должен делать последний параметр в SelectOneMenu, выбранном независимо от значения в bean-компоненте. С return false; это будет первый вариант.

Другой возможной причиной может быть (как упомянуто в других постах - я только включаю это здесь, чтобы помочь с другими, кто еще не нашел его) список объектов, которые отображает selectOneMenu, перезагружаемый во время / сразу после того, как слушатель RowEditEvent называется.

У меня было такое же поведение, как описано в OP (PrincAm), и я бесконечно рефакторировал методы equals() и hashCode() (даже написал столько тестовых примеров, сколько смог придумать, чтобы доказать это); методы equals() и hashCode() были правильными, но поведение все еще сохранялось. Я даже рефакторил метод equals(), чтобы он всегда возвращал true или всегда возвращал false, и значение selectOneMenu будет установлено на первый или последний пункт меню, соответственно.

Только после краткого упоминания о возможности перезагрузки значений я вернулся и посмотрел, как / когда эта коллекция загружалась; Я обнаружил, что во время действия метода, который сохранил строку таблицы данных, я бы вызвал метод refresh(), который перезагрузил коллекцию выбираемых значений. Как только я реорганизовал свой код, чтобы НЕ перезагружать этот список, selectOneMenu сохранит правильное значение, выбранное, как предполагалось.

Опять же, просто добавив еще одно возможное решение этой ОЧЕНЬ раздражающей и несколько неясной проблемы. Слава как PrincAm и JaqenH'ghar за их публикации в качестве ценных ресурсов для других.

Другие вопросы по тегам