6

我今天正在寻找一些关于我遇到的问题的指导。

我想要完成的是动态构建一个带有验证和所有内容的页面。最终结果是允许用户通过管理功能配置页面上的字段。下面是我用作测试页面的代码副本,我在其中循环“配置”字段并使用定义的条件写出字段。

<ui:repeat var="field" value="#{eventMgmt.eventFields}" varStatus="status">
  <div class="formLabel">
    <h:outputLabel value="#{field.customName}:"></h:outputLabel>
  </div>
  <div class="formInput">
    <h:inputText id="inputField" style="width:# {field.fieldSize gt 0 ? field.fieldSize : 140}px;">
      <f:validateRegex  disabled="#{empty field.validationPattern}" pattern="#{field.validationPattern}"></f:validateRegex>
    </h:inputText>
    <h:message for="inputField" showDetail="true" errorClass="errorText"></h:message>
  </div>
</ui:repeat>

在页面呈现并尝试提交该字段的任何值后,我收到以下消息“Regex 模式必须设置为非空值”。这显然意味着没有填充表达式。让我感兴趣的是,在评估 EL 时,没有表达式的字段将被禁用。我也可以将相同的代码#{field.validationPattern} 放入页面中,然后将正确的值写入页面。

所以,我的问题是: 1. 这可能吗?2. JSF 容器在什么时候考虑为验证正则表达式绑定模式?3.我做错了什么或正确的方法是什么?

我正在运行 Tomcat 7.0.22、Mojarra 2.1.5 和 Eclipse 作为我的 IDE。

4

1 回答 1

15

这是由于使用<f:validateRegex>其属性取决于当前迭代的<ui:repeat>.

标签是标签处理程序,而<f:xxx>不是 UI 组件。在视图构建期间构建 UI 组件树时,会解析和评估标记处理程序。在视图构建期间评估所有 EL。<h:xxx>标签和一些<ui:xxx>类似的标签是<ui:repeat>UI 组件。他们所有的 EL 在视图渲染期间进行评估。

因此,在您的情况下,当<f:validateRegex>被解析和执行时,#{field}在当前 EL 范围内不可用,因此评估为null.

有几种方法可以让它工作。

  • 将验证器移动到表示Field并引用它的类,如下所示:

    <h:inputText ... validator="#{field.validate}" />
    

    Field你手动实例化它的类中:

    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        if (pattern != null) {
            RegexValidator regexValidator = new RegexValidator();
            regexValidator.setPattern(pattern);
            regexValidator.validate(context, component, value);
        }
    }
    

  • 或者,包装#{eventMgmt.eventFields}aListDataModel<Field>并将验证器绑定到#{eventMgmt}bean。这样,您将能够根据行数据设置验证器的属性:

    <h:inputText ... validator="#{eventMgmt.validate}" />
    

    在后面的支持 bean 类中#{eventMgmt}

    private DataModel<Field> model;
    private RegexValidator regexValidator;
    
    @PostConstruct
    public void init() {
        regexValidator = new RegexValidator();
    }
    
    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        String pattern = model.getRowData().getPattern();
    
        if (pattern != null) {
            regexValidator.setPattern(pattern);
            regexValidator.validate(context, component, value);
        }
    }
    

  • 或者,创建一个自定义Validator扩展RegexValidator并将模式设置为组件的自定义属性,<f:attribute>然后让Validator拦截。基本上使用<f:attribute>unevalated 向组件添加一个新属性ValueExpression,因此当您调用它时会重新评估它。例如:

    <h:inputText ...>
        <f:validator validatorId="extendedRegexValidator" />
        <f:attribute name="pattern" value="#{field.pattern}" />
    </h:inputText>
    

    @FacesValidator("extendedRegexValidator")
    public class ExtendedRegexValidator extends RegexValidator {
    
        @Override
        public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
            String pattern = (String) component.getAttributes().get("pattern");
    
            if (pattern != null) {
                setPattern(pattern);
                super.validate(context, component, value);
            }
        }
    
    }
    

  • 或者,如果您碰巧使用 JSF 实用程序库OmniFaces,请使用它的<o:validator>. 例如

    <h:inputText ...>
        <o:validator validatorId="javax.faces.RegularExpression" pattern="#{field.pattern}" />
    </h:inputText>
    

    是的,仅此而已。这<o:validator>将确保所有属性都被评估为延迟表达式而不是立即表达式。

也可以看看:

于 2012-02-08T14:36:08.077 回答