【问题标题】:Primefaces `required` attribute bug : How to fix it?Primefaces `required` 属性错误:如何修复?
【发布时间】:2017-11-29 20:24:02
【问题描述】:

我被这个错误逼疯了:

我有以下字段

<p:selectOneMenu id="selectOption"
        required="true"
        requiredMessage="#{bundle.mandatory_field_message}"
        rendered="#{myBean.previousOptionSelected eq 'Correct Option'}"
        value="#{myBean.selectedOption}">
    <c:if test="#{myBean.optionsList.size() ne 1}">
        <f:selectItem itemLabel="#{bundle.default_select}" itemValue="null" />
    </c:if>
    <f:selectItems value="#{myBean.optionsList}" var="opt"
            itemValue="#{opt}" itemLabel="#{opt.description}" />
    <f:ajax event="change" render="msgSelectOption" />
</p:selectOneMenu>
<p:messages id="msgSelectOption" for="selectOption" display="text" />

当我尝试提交包含该字段的表单时,即使选择了一个值并且实际正确分配了 bean 中的值,也会显示 requiredMessage

我目前正在使用 primefaces 5.3 和 jsf 2.0(否:无法升级)

【问题讨论】:

  • 您无法升级生产,但您可以只是为了解决这个问题尝试更新版本,看看它是否是偶然修复的。然后,您离找到解决方法或为您使用的 PF 版本创建解决该问题的补丁更近了一步……干杯(为什么您在 PF 组件中使用 f:ajax 而不是 p:ajax
  • 在纠正这个错误之前,我没有处理这个特定的组件。我通常使用p:ajax,但老实说,除了组件属性名称之外,我看不出有什么区别
  • 令我困扰的是,它是整个表单中唯一这样的组件。而且我有几个领域几乎以相同的方式构建,工作得很好。
  • 我有 2 条建议供您调查: 1. 也许 Faces Converter 以某种方式失败(尽管我没有看到它在代码 sn-p 中定义)。 2.可能optionsList的getter在bean中没有正确初始化。
  • 我没有这个字段的转换器。列表创建的对象是与输入值相同的类的实例。我已经使用调试器检查了 getter,并且列表已正确初始化(另一个证明是我在加载页面时看到了正确的值)

标签: jsf primefaces


【解决方案1】:

我几乎找到了答案here,但我仍然会在这篇文章中解释,因为参考答案没有直接解决这个特定问题:

代码示例中使用的对象似乎没有经过任何类型的转换。虽然我以前可以在没有转换器的情况下使用对象,但它们实际上是 enum 而这个不是。所以似乎每当我需要一个不是枚举的自定义对象时,我都需要为它创建一个转换器(手动将数据序列化为字符串或简单地使用 id 并从可能的对象列表中恢复数据)

这对我有用:

<p:selectOneMenu id="selectOption"
        converter="optionConverter"
        required="true"
        requiredMessage="#{bundle.mandatory_field_message}"
        rendered="#{myBean.previousOptionSelected eq 'Correct Option'}"
        value="#{myBean.selectedOption}">
    <c:if test="#{myBean.optionsList.size() ne 1}">
        <f:selectItem itemLabel="#{bundle.default_select}" itemValue="" />
    </c:if>
    <f:selectItems value="#{myBean.optionsList}" var="opt"
            itemValue="#{opt}" itemLabel="#{opt.description}" />
    <f:ajax event="change" render="msgSelectOption" />
</p:selectOneMenu>
<p:messages id="msgSelectOption" for="selectOption" display="text" />

使用以下转换器:

@FacesConverter(forClass = myPackage.OptionClass.class, value="optionconverter")
public class OptionConverter implements Converter{

    public Object getAsObject(FacesContext facesContext, UIComponent component, String submittedValue) {
        if (submittedValue != null && !submittedValue.trim().equals("")) {
            for (OptionClass opt : OptionListingService.getEntries()) {
                if (submittedValue.equalsIgnoreCase(opt.getUniqueID())) {
                    return opt;
                }
            }
        }
        return null;
    }

    public String getAsString(FacesContext facesContext, UIComponent component, Object value) {
        if (value == null || value.equals("")) {
            return "";
        } else {
            return ((OptionClass)value).getUniqueID();
        }
    }
}

另外请注意,我在此项中将itemValue="null" 的值更改为itemValue=""

<f:selectItem itemLabel="#{bundle.default_select}" itemValue="" />

这是必要的,因为转换器会将值解释为字符串,因此会尝试将id 等于"null" 的字符串值转换。代码仍然可以工作,但我喜欢(这也是一种更好的做法)尽可能干净地操作数据。

感谢 Dusan Kovacevic 指出可能的转换器问题。

【讨论】:

  • 这样可以吗? :)
猜你喜欢
  • 1970-01-01
  • 2021-08-14
  • 1970-01-01
  • 2021-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-05
相关资源
最近更新 更多