validation - 验证 ui :repeat 中项目的顺序

标签 validation jsf uirepeat

我正在 JSF 2 中编写验证器方法。我有一个 ui:repeat我的页面中呈现项目列表的元素。每个项目都有一个日期属性,我需要确保日期以特定的顺序相互对应,例如列表中最后一项的日期不早于第一项的日期。我试图获取 ui:repeat 中的所有子元素并迭代它们以进行比较,但我真的不知道从哪里开始。我已经看到如何通过 ID 获取特定元素:

UIInput input = (UIInput) context.getViewRoot().findComponent(elementId);

然而,在ui:repeat内JSF 使 ID 值唯一,所以我不知道它们在编译时是什么。此外,在编译时我不知道列表中有多少项。

我已经查看了 UIViewRoot 的 Javadoc和其他相关的类,并尝试了一些东西,但我遇到了错误,东西不起作用,我真的不知道我是否接近到达任何地方。我将我的尝试代码从这篇文章中删除,因为它们可能是一个笑话。

最佳答案

物理上只有 UIInput其状态根据 UIRepeat 的当前迭代轮变化而变化的组件.它仅通过其客户端 ID 可用,无需 UIRepeat索引:findComponent("formId:inputId") (UIRepeat 索引仅在客户端有意义)。但是,当组件以编程方式在 UIRepeat 的上下文之外被访问时这样,那么它确实会返回一个看似空的状态。

为了访问UIInput所有这些状态的组件,因为它们在 UIRepeat 中并收集它们的值,您需要运行 UIComponent#visitTree() UIRepeat .

这是一个启动示例:

<ui:repeat value="#{bean.items}" var="item">
    <f:event type="postValidate" listener="#{bean.validateOrder}" />
    <h:inputText value="#{item.value}" />
</ui:repeat>

有了这个 validateOrder()方法(同样,只是一个启动示例,这种方法天真地假设中继器中只有一个 UIInput 组件):
@SuppressWarnings("rawtypes")
public void validateOrder(ComponentSystemEvent event) {
    final FacesContext context = FacesContext.getCurrentInstance();
    final List<Comparable> values = new ArrayList<Comparable>();

    event.getComponent().visitTree(VisitContext.createVisitContext(context), new VisitCallback() {
        @Override
        public VisitResult visit(VisitContext context, UIComponent target) {
            if (target instanceof UIInput) {
                values.add((Comparable) ((UIInput) target).getValue());
            }
            return VisitResult.ACCEPT;
        }
    });

    boolean ordered = new ArrayList<Comparable>(new TreeSet<Comparable>(values)).equals(values);

    if (!ordered) {
        event.getComponent().visitTree(VisitContext.createVisitContext(context), new VisitCallback() {
            @Override
            public VisitResult visit(VisitContext context, UIComponent target) {
                if (target instanceof UIInput) {
                    ((UIInput) target).setValid(false);
                }
                return VisitResult.ACCEPT;
            }
        });

        context.validationFailed();
        context.addMessage(null, new FacesMessage("Values are not in order!"));
    }
}

请注意,它访问了树两次;第一次收集值,第二次将这些输入标记为无效。另请注意,使用标准 JSF 验证器无法完成此非常具体的要求。您不能附加 <f:validator><ui:repeat> .贴在 <h:inputText>理论上是可能的,但它会导致相同的验证器运行与重复项目数量一样多的次数,这是没有意义的。此外,验证器需要接受 getSubmittedValue()对比 getValue()考虑到这种方式。

OmniFaces 有一个 <o:validateOrder> 组件在固定组件上做类似的事情,但它不是为在动态重复的组件中使用而设计的。

关于validation - 验证 ui :repeat 中项目的顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18469551/

相关文章:

JavaScript表单验证问题

没有dataModel的JSF 2 dataTable行索引

java - 如果数组中输入的数据小于零,我试图创建一条错误消息,输入验证

jsf - 使用 h :commandButton 通过 POST 打开新窗口

java - JSF 和 Richfaces 丰富 :select and f:selectItems

java - 如何使用java上传文件到http远程服务器?

java - 具有 <ui :repeat> 的不同 div 标签 id

JSF h :selectBooleanCheckbox inside ui:repeat - varStatus. 索引有效,var 无效

python - 如何防止 Pydantic 在 ValidationError 上抛出异常

javascript - 使用数组或变量的 jquery 验证器正则表达式