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 за их публикации в качестве ценных ресурсов для других.