验证ui中的项目顺序:重复

nei*_*zan 4 validation jsf uirepeat

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

UIInput input = (UIInput) context.getViewRoot().findComponent(elementId);
Run Code Online (Sandbox Code Playgroud)

但是,在ui:repeatJSF中ID值是唯一的,所以我不知道它们在编译时是什么.此外,在编译时我不知道列表中将有多少项.

我已经看过Javadoc for UIViewRoot和其他相关的类,并且已经尝试了几件事,但是我遇到了错误,事情没有用,而且我真的不知道我是否已经接近任何地方了.我将离开这篇文章的代码留下来,因为他们可能是个笑话.

Bal*_*usC 6

实际上只有一个 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>
Run Code Online (Sandbox Code Playgroud)

使用这种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!"));
    }
}
Run Code Online (Sandbox Code Playgroud)

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

OmniFaces有一个<o:validateOrder>在固定组件上做类似事情的组件,但它不适用于动态重复组件.