【发布时间】:2016-07-19 18:17:26
【问题描述】:
我不明白为什么这个问题是重复的。如果我调试代码然后 - 单击按钮时 - 没有检测到 projectSelected 的新值。甚至hashCode 也是一样的。 ProjectEntity 的 equals 方法仅包含相同的 id,因为它来自数据库并且在任何地方都没有更改。选择中不存在空值。
但是,有太多代码无法重现该问题。我删除了不必要的代码,问题仍然存在。
原始问题:在以下带有 3 个 <p:selectOneMenu> 字段的表单中,如果单击提交按钮,则会为 projectSelector 字段触发 valueChangeEvent,尽管它没有更改。这是为什么?就像按钮后面的实际操作永远不会被调用。我希望 valueChangeEvent 只有在项目发生变化时才会被解雇。
更新:试图找出原因,我将 ProjectEntity 替换为 String,然后它起作用了。所以我认为它必须是 ProjectEntity 的 equals 方法,但它只比较 id。我进一步调试,发现所选值正在与所有字段设置为 null 的 ProjectEntity 进行比较,这给出了一个错误,因此是一个 valueChangeEvent。所以问题是为什么有一个所有字段都设置为 null 的 ProjectEntity?我调试了 UIInput.compareValues,它的“null”-ProjectEntity 是以前的值。这是由 UIOuput.getLocalValue 返回的。它来自哪里?
Update2:即使使用 selectOneMenu shows after submit always the last item in the list as selected item 中的 equals 和 hashCode,行为也不会改变。我创建了一个 ear file 很容易部署到例如一只野蝇,因为我被困在这个问题上,所以会很感激任何帮助。
<h:form>
<p:outputLabel value="#{msgs.timeProject}"/>
<p:selectOneMenu value="#{timeBean.model.projectSelected}"
converter="projectConverter"
onchange="submit()"
valueChangeListener="#{timeBean.projectChanged}"
immediate="true"
required="true">
<f:selectItems value="#{timeBean.model.allProjects}"
var="singleProject"
itemValue="#{singleProject}"
itemLabel="#{singleProject.name}"/>
</p:selectOneMenu>
<p:commandButton value="#{msgs.send}"
action="#{timeBean.myAction}"
ajax="false"/>
<p:outputLabel value="#{timeBean.model.resultValue}"
rendered="#{not empty timeBean.model.resultValue}"/>
</h:form>
转换器
@FacesConverter(value = "projectConverter")
public class ProjectConverter implements Converter {
@Inject
private ProjectService projectService;
@Override
public Object getAsObject(final FacesContext facesContext, final UIComponent uiComponent, final String projectName) {
if (StringUtils.isEmpty(projectName)) {
return null;
}
final List<ProjectEntity> projects = projectService.findAll();
for (ProjectEntity project : projects) {
if (StringUtils.equals(projectName, project.getName())) {
return project;
}
}
return null;
}
@Override
public String getAsString(final FacesContext facesContext, final UIComponent uiComponent, final Object value) {
if (value == null) {
return null;
}
if (value instanceof ProjectEntity) {
return ((ProjectEntity) value).getName();
}
return "???projectName???";
}
}
ProjectEntity 的 equals 方法
@Override
public boolean equals(final Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
final ProjectEntity that = (ProjectEntity) o;
return id != null ? id.equals(that.id) : that.id == null;
}
还有timeBean里面的变化监听器
public void projectChanged(final ValueChangeEvent event) {
final ProjectEntity projectSelected = (ProjectEntity) event.getNewValue();
model.setProjectSelected(projectSelected);
final FacesContext context = FacesContext.getCurrentInstance();
context.renderResponse();
}
时间模型
public class TimeModel {
private ProjectEntity projectSelected;
private List<ProjectEntity> allProjects;
private String resultValue;
... getters and setters ...
【问题讨论】:
-
这是重现您的问题所需的绝对最少代码量吗?
-
您确认该值实际上没有改变吗?即使您没有在 UI 中触摸此特定选择,它也可能发生。例如,如果
#{timeBean.model.projectSelected}的初始值不在#{timeBean.model.allProjects}中(例如null),那么第一个POST 将发布#{timeBean.model.allProjects}中的第一个项目,并且ValueChangeListener 将被触发。 -
如果提交(commandButton)被点击,它会执行同样的任务,即
submit()表单。这与 selectMenu 的onChange事件调用的函数相同 -
我认为你的问题很正确。不幸的是,标签金徽章所有者的行为有点不可预测。我建议检查受骗者,并检查它是否回答了您的问题。如果没有,请在评论中非常清楚地解释它!你得到了我的重新投票。
-
顺便说一句,您的建议非常好!但是... 标记金徽章拥有者不会做不可预测的事情。相反。 99.5% 他们是对的。他们在空闲时间(比如喝啤酒)阅读了很多问题来帮助他人,凭借他们所拥有的所有知识,他们可以通过快速扫描帖子来获得非常高的“阳性重复”率。但是,是的,它们是人类,因此偶尔可能会出现错误。如果从一开始就创建了minimal reproducible example,这很可能会进一步减少。然而,许多人并没有这样做,因为他们希望其他人具有千里眼,即使是标签金徽章的拥有者也不是。
标签: jsf primefaces