【问题标题】:Setting a validator attribute using EL based on ui:repeat var使用基于 ui:repeat var 的 EL 设置验证器属性
【发布时间】:2012-02-29 23:30:50
【问题描述】:

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

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

<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。

【问题讨论】:

    标签: validation jsf-2 el uirepeat


    【解决方案1】:

    这是由使用&lt;f:validateRegex&gt; 引起的,其属性取决于&lt;ui:repeat&gt; 的当前迭代项。

    &lt;f:xxx&gt; 标签是标签处理程序,而不是 UI 组件。在视图构建期间构建 UI 组件树时,会解析和评估标记处理程序。在视图构建期间评估所有 EL。 &lt;h:xxx&gt; 标记和一些 &lt;ui:xxx&gt; 标记(如 &lt;ui:repeat&gt;)是 UI 组件。它们的所有 EL 都会在视图渲染期间进行评估。

    因此,在您的情况下,当 &lt;f:validateRegex&gt; 被解析和执行时,#{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} 包装在ListDataModel&lt;Field&gt; 中,并将验证器绑定到#{eventMgmt} bean。这样您就可以根据行数据设置验证器的属性:

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

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

      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);
          }
      }
      

    • 或者,创建一个扩展RegexValidator 的自定义Validator,并通过&lt;f:attribute&gt; 将模式设置为组件的自定义属性,然后让Validator 拦截它。 &lt;f:attribute&gt; 基本上是为组件添加了一个新属性,带有未评估的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,请使用它的 &lt;o:validator&gt;。例如

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

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

    另见:

    【讨论】:

    • 你太棒了!!非常感谢您长期健康的回答。如果这是在您的盘子上,您会选择哪种方法作为最佳方法。作为我的道路,我被绑在 #1 和 #3 之间。
    • 不客气。我会选择#1。在这种“动态形式”的方法中,它应该是 Field 类本身的责任,它也为更好的抽象打开了大门。
    • 我选择了#1,只花了几分钟就让一切运行起来。我必须做的唯一更改是初始化 RegexValidator。极好的!再次感谢您的帮助。
    • 谢谢 :) 我选择了#3。很好的解释
    猜你喜欢
    • 1970-01-01
    • 2013-08-23
    • 2013-03-18
    • 2011-07-24
    • 1970-01-01
    • 1970-01-01
    • 2020-07-17
    • 2017-10-13
    相关资源
    最近更新 更多