JSF 2.0;Validator标记“disabled”取决于页面的值

4
在我的jsf应用程序中,我想验证一个字段,只有在选择单选按钮中的一个选项被选中时才应该进行验证。
我发现有一个名为“disabled”的属性。
我可以使用它来检查另一个字段的值吗?
我尝试过,但我无法访问我的bean中的值。
<h:selectOneRadio value="#{myBean.checkedSelectOneRadioValue}">
    <f:selectItems value="#{myBean.valuesForSelectOneRadio}" />
</h:selectOneRadio>


<f:validator validatorId="myValidator" disabled="#{myBean.checkedSelectOneRadioValue == 'TEST'}" />

有没有不需要编写自己的验证处理程序就能实现这一点的方法?
谢谢!

你的禁用检查看起来有些可疑,它不应该是 "#{myBean.checkedSelectOneRadioValue == 'TEST'}" 吗?还是这只是一个错别字(移动花括号)? - Volker
我也尝试了你的版本,但它并没有起作用。可能是因为在验证的那一刻,SelectOneRadio 中的值没有存储在 bean 中吗? - Tobi
尝试在selectOneRadio标记中设置partialSubmit="true",这应该可以提交值。 - Volker
我的脸上是否存在partialSubmit,或者有其他替代方法? - Tobi
我无法使用ajax。验证器位于另一个字段中,只有在selectoneradio选择特定值时才需要验证。 - Tobi
3个回答

11
<f:validator> 是一个标签处理器,而不是UI组件。所有的属性都在视图构建时被定义评估,而不是在视图渲染时评估。视图构建时间是指将XHTML文件解析为JSF组件树的那个时刻,这些组件可以通过context.getViewRoot()访问。通常情况下,通过在(ajax)操作中返回null/void来重用相同的视图。

因此,您不能使标签处理器属性依赖于可能在postback请求期间更改的渲染时间属性。其中一种方法是在自定义验证器本身内执行该检查。

例如:

<h:inputText>
    <f:validator validatorId="myValidator" />
    <f:attribute name="radio" value="#{myBean.checkedSelectOneRadioValue}" />
</h:inputText>

使用

@Override
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {     
    if (!"TEST".equals(component.getAttributes().get("radio"))) {
        return;
    }

    // Perform actual validation here.
}

你也可以使用OmniFaces <o:validator>。这个扩展了标准的<f:validator>,支持对属性中EL表达式的请求基础评估。
<h:inputText>
    <o:validator validatorId="myValidator" disabled="#{bean.checkedSelectOneRadioValue == 'TEST'}" />
</h:inputText>

请参考展示示例源代码,下面发布了一个相关的摘录:
@Override
public void apply(FaceletContext context, UIComponent parent) throws IOException {
    if (!ComponentHandler.isNew(parent)) {
        return;
    }

    final javax.faces.validator.Validator validator = createValidator(context);
    final RenderTimeAttributes attributes = collectRenderTimeAttributes(context, validator);
    final ValueExpression disabled = getValueExpression(context, "disabled", Boolean.class);
    ((EditableValueHolder) parent).addValidator(new javax.faces.validator.Validator() {

        @Override
        public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
            if (disabled == null || Boolean.FALSE.equals(disabled.getValue(context.getELContext()))) {
                attributes.invokeSetters(context.getELContext(), validator);
                validator.validate(context, component, value);
            }
        }
    });
}

<o:validator> 让我的一天充满了喜悦! - ForguesR

0

使用JSF 2.0,您可以使用f:ajax进行部分提交。将此标签添加到您的h:selectOneRadio中:

<h:selectOneRadio value="#{myBean.checkedSelectOneRadioValue}">
    <f:ajax render="idOfInputText"/>
    <f:selectItems value="#{myBean.valuesForSelectOneRadio}" />
</h:selectOneRadio>
...
<h:inputText id="idOfInputText">
    <f:validator validatorId="myValidator" 
                 disabled="#{myBean.checkedSelectOneRadioValue eq 'TEST'}" />
</h:inputText>

render属性的内容替换为验证器输入字段的真实ID。这假定selectOneRadio和inputText位于同一NamingContainer中。


我也尝试了这个例子,但它不起作用。现在我相信,在这里发生了一些奇怪的事情 :-/ 我是否需要为selectoneradio和/或inputtext使用绑定? - Tobi
最终,我找到了一个解决方案。现在我将在myBean中进行验证,一切都按预期工作。感谢您的帮助!!! - Tobi

-1
为避免在评论中进行长时间讨论,我将提供我的建议作为答案,以便进一步讨论...
首先应该是 disabled="#{myBean.checkedSelectOneRadioValue == 'TEST'} 或者 disabled="#{myBean.checkedSelectOneRadioValue eq 'TEST'} 此外,在ICEFaces中(MyFaces也应该有这个功能),您可以使用:
<h:selectOneRadio value =“#{myBean.checkedSelectOneRadioValue}” partialSubmit =“true”> <f:selectItems value =“#{myBean.valuesForSelectOneRadio}”/> </h:selectOneRadio>
这应该会在更改selectoneradio的值后强制进行ajax请求,并且验证程序已禁用检查应该能够从bean中获取它。
如果这样不起作用,MyFaces中可能会有autoSubmit或类似的东西...

不起作用 :-( 我尝试使用partialSubmit,eq和==,但验证器不会按照我的预期工作。至少,我尝试将'TEST'设置为null,并且它可以工作。所选值将不会写入bean中。我可以使用valueChangeListener将值存储在bean中吗? - Tobi
你在哪个组件中使用验证器?它是否具有partialSubmits、immediates或其他功能?新值是否未被写入你的bean,或者你的视图没有从中接收到它? - Volker
验证器位于inputText中。是否还应该有partialSubmit属性? - Tobi
partialSubmit 只存在于 <ice:xxx> 组件系列的 ICEfaces 组件中。OP 没有以任何方式表明他/她正在使用 ICEfaces。在标准的 JSF2 中,有 <f:ajax> 可以完成这项工作。 - BalusC
那么,你使用什么?MyFaces还是标准JSF还是其他的?<t:xxx>,<tr:xxx>?为什么使用<h:selectOneRadio>而不是<tr:selectOneRadio>?Trinidad可能具有自动提交功能,其他类似功能如<f:ajax>... - Volker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接