【问题标题】:Refresh JSF validator attributes on rerender在重新渲染时刷新 JSF 验证器属性
【发布时间】:2010-12-14 13:52:24
【问题描述】:

我对验证器组件的属性值有疑问。 显然验证器是在我第一次访问页面时创建的。

请看我下面的代码:

<h:inputText value="#{qsetting.value}" rendered="#{qsetting.dataType=='Double'}">  
   <mw:validateRange min="#{qsetting.minValue}" max="#{qsetting.maxValue}" />  
</h:inputText>

inputText 组件通过 ajax 重新呈现,但显然包括显示的值。 不幸的是,qsetting.minValue 和 qsetting.maxValue 没有刷新,导致我的验证器无法正常工作。

是否有可能刷新验证器,以确保它重新检索其属性或创建验证器的新实例? 验证器类本身目前正在实现“验证器,可序列化”。 另外,我正在使用带有 facelets 的 jsf1.2...

谢谢, 史蒂文

【问题讨论】:

  • 如果您标记mw 会有所帮助。我不知道那是什么。那可能是自定义组件吗?
  • 是的,它是一个自定义验证器。不过那里没什么特别的,只有 2 个 Double 成员变量,都有一个 getter 和一个 setter。问题基本上是只有在构建页面时才会调用 getter。所以在重新渲染时,组件树存在,验证器的设置器不会被调用。因此我的验证器中有不正确的值,我想以某种方式修复它......(没有测试,但我相信你会得到与 f:valiateLongRange 标签相同的结果)

标签: jsf facelets validation


【解决方案1】:

这些年来,我在非 ajax 环境中遇到过几次这个问题,今天又遇到了。添加 Ajax 并没有真正改变任何东西,因为一旦页面最初构建、ajax 或其他方式,验证器属性就不会再次评估。

我想出的唯一解决方案是将验证器属性设置为验证器表达式,然后在 validate 方法中评估该表达式。

我遇到的另一个问题(JSF 1.2 和 Facelets 也是如此)是并非所有 EL 变量都有效。我必须使用静态托管 bean 作为表达式的根来访问该值。作为根的 facelet ui:param 值不起作用。我还没有测试看看还有什么可能无法正确评估。这可能是由于 JSF 本身设计中的另一个错误造成的。见http://myfaces.apache.org/core12/myfaces-api/apidocs/javax/faces/context/FacesContext.html#getELContext%28%29。

例如,而不是:

max="#{qsetting.maxValue}"

使用

maxExpression="qsetting.maxValue"

然后

public String getMax(FacesContext context) {
    Application app = context.getApplication();
    ExpressionFactory exprFactory = app.getExpressionFactory();
    ValueExpression ve = exprFactory.createValueExpression(context.getELContext(),
            "#{" + getMaxExpression() + "}",
            String.class);

    Object result = ve.getValue(context.getELContext());

    return (String)result;
}

public String getMaxExpression() {
    return this.maxExpression;
}

public void setMaxExpression(String maxExpression) {
    this.maxExpression = maxExpression;
}


//// StateHolder

public boolean isTransient() {
    return isTransient;
}

public void setTransient(boolean newTransientValue) {
    isTransient = newTransientValue;
}

public Object saveState(FacesContext context) {
    Object[] state = new Object[1];
    state[0] = maxExpression;
    return state;
}

public void restoreState(FacesContext context, Object state) {
    Object[] values = (Object[]) state;
    maxExpression = (String) values[0];
}

2012 年 9 月 19 日更新:

在调查 MyFaces Commons 如何解决此问题后,更好的解决方案是更改 Facelets 用于评估验证器和转换器属性表达式的规则。

它基本上归结为添加一个新的验证器或转换器 MetaRule,当应用它时,它会检查属性值是否是非文字的。如果它是非文字的,请在您的验证器或转换器上调用一个特殊方法,该方法传入值表达式而不是当前值。

http://svn.apache.org/viewvc/myfaces/commons/trunk/myfaces-commons-validators/src/main/java/org/apache/myfaces/commons/validator/_ValidatorRule.java?view=markup

此时的验证器需要将值表达式存储为状态,并在需要时对其进行评估。 MyFaces commons 提供了所有复杂的基础架构来实现这一点,但您可以转储所有这些并编写一个简单的自定义规则并自己直接管理 ValueExpression,类似于我最初发布的内容。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-23
    • 2010-11-12
    • 2011-02-06
    • 2011-09-09
    • 1970-01-01
    • 2019-08-20
    相关资源
    最近更新 更多