【问题标题】:ValueChangeEvent although value has not changedValueChangeEvent 虽然值没有改变
【发布时间】: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


【解决方案1】:

我猜,问题存在于 ProjectConverter 类中,因为分配有效的 projectService 实例可能会遇到麻烦。也许您删除了注入并尝试通过显式 cdi-finders 在 getAsObject、getAsString 方法中以编程方式计算值。

我记得在注入 ServletFilter 时曾在类似的情况下运行过。

【讨论】:

    猜你喜欢
    • 2018-12-02
    • 1970-01-01
    • 2011-06-15
    • 1970-01-01
    • 2017-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多