我有一个只有一个选择的数据表。选择一行并按下按钮后,将打开带有输入文本和选择一个菜单的对话框。输入文本和一个菜单应包含所选行的数据。通常,它是一个用于编辑数据表中记录的对话框。
但是,在对话框中选择一个菜单将不会根据所选行更改默认值。它与<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>
答案 0 :(得分:3)
当SelectOneMenu和类似组件无法按预期工作时,应检查转换器并确保实体/ pojos上有equals()和hashCode()方法。在这种情况下,您缺少两种方法。从BalusC的post复制的简单实现是:
@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可以为null,则需要在这些方法中使用更多字段。也可以使用Apache Commons / Lang HashCodeBuilder和EqualsBuilder,如答案here中所述。
要验证框架实际调用这些方法,您可以尝试在equals方法中只return true;
,这应该始终使SelectOneMenu中的最后一个选项被选中,无论bean中的值如何。使用return false;
,它将是第一个选项。
答案 1 :(得分:0)
另一个可能的原因可能是(正如其他帖子中所提到的 - 我只是将其包含在这里以帮助其他尚未找到它的人)selectOneMenu正在显示的对象列表是在/之后/之后重新加载的调用RowEditEvent侦听器。
我有与OP(PrincAm)描述的相同的行为,并且无休止地重构了equals()&amp; hashCode()方法(甚至可以编写尽可能多的单元测试用例来证明它们);等于()&amp; hashCode()方法是正确的,但行为仍然存在。我甚至重构了equals()方法以始终返回true或始终返回false,并且selectOneMenu值将分别设置为第一个菜单选项或最后一个菜单选项。
只有在简要提及重新加载值的可能性之后,我才回过头来看看如何/何时加载该集合;我发现在保存数据表行的action方法中,我会调用一个refresh()方法,该方法重新加载了可选值的集合。一旦我重构我的代码以不重新加载该列表,selectOneMenu将保持按预期选择正确的值。
再次,只是为这个非常烦人且有些模糊的问题添加另一个可能的解决方案。感谢PrincAm&amp; JaqenH'ghar将他们的帖子作为其他人的宝贵资源。