问题描述
我正在JSF 2中编写一个验证器方法.我的页面中有一个ui:repeat
元素,用于显示项目列表.每个项目都有一个date属性,我需要确保日期以特定的顺序相互对应,例如列表中最后一项的日期不早于第一项的日期.我试图在ui:repeat中获取所有子元素,并对其进行迭代以进行比较,但是我真的不知道从哪里开始.我已经看到了如何通过ID获取特定元素:
I'm writing a validator method in JSF 2. I have a ui:repeat
element in my page that renders a list of items. Each item has a date property, and I need to ensure the dates correspond to each other in a specific sequence, e.g. the date of the last item in the list doesn't come before the date of the first item. I was trying to get all the child elements inside the ui:repeat and iterate over them to do the comparison, but I don't really know where to start. I've seen how to get a specific element by ID:
UIInput input = (UIInput) context.getViewRoot().findComponent(elementId);
但是,在ui:repeat
中,ID值是由JSF唯一的,所以我不知道它们在编译时是什么.此外,在编译时,我不知道列表中将有多少项.
However, within the ui:repeat
the ID values are made unique by JSF, so I don't know what they are at compile time. Furthermore, at compile time I don't know how many items there will be in the list.
我已经查看了UIViewRoot
和其他关联类的Javadoc,并尝试了一些方法,但是我遇到了错误,这些方法不起作用,并且我真的不知道自己是否在甚至接近到任何地方.我将尝试的代码遗漏在本文之外,因为它们可能只是在开玩笑.
I've looked at the Javadoc for UIViewRoot
and other associated classes, and have tried a couple things, but I'm getting errors, things aren't working, and I don't really know if I'm even close to getting anywhere. I'm leaving the code of my attempts out of this post, becuase they're probably a joke.
推荐答案
在物理上只有一个 UIInput
组件,其状态根据UIRepeat
的当前迭代周期而变化.仅通过其客户端ID即可使用,而没有UIRepeat
索引:findComponent("formId:inputId")
(UIRepeat
索引仅在客户端具有重要意义).但是,当以这种方式在UIRepeat
上下文之外以编程方式访问该组件时,它实际上将返回一个看似空的状态.
There's physically only one UIInput
component whose state changes depending on the current iteration round of UIRepeat
. It's available by just its client ID without the UIRepeat
index: findComponent("formId:inputId")
(the UIRepeat
index is only of significance in the client side). However, when the component is programmatically been accessed outside the context of UIRepeat
this way, then it'll indeed return a seemingly empty state.
为了访问处于所有状态的UIInput
组件,并收集它们的值,您需要运行 UIComponent#visitTree()
UIRepeat上的a>.
<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!"));
}
}
OmniFaces有一个 <o:validateOrder>
组件,它在固定组件上做类似的事情,但它不适用于动态重复的组件.
OmniFaces has an <o:validateOrder>
component which does a similar thing on fixed components, but it isn't designed for usage in dynamically repeated components.
这篇关于验证ui:repeat中项目的顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!