您尝试将输入组件绑定到映射/数组失败,因为 JSF 组件树中没有多个这些组件,而只有一个。这<ui:repeat>
在生成 JSF 组件树的视图构建期间不会运行。相反,它在视图渲染期间运行,生成 HTML 输出。换句话说,子组件<ui:repeat>
在每次迭代生成 HTML 输出期间每次都会重用。
特殊的例外是,“目标无法到达,''BracketSuffix'' 返回 null”被抛出是因为变量#{_lang}
在视图构建期间不可用,即构建 UI 组件树的那一刻以及所有id
and binding
属性被评估。它仅在视图渲染期间可用。
如果您使用的话,这些绑定尝试就会成功<c:forEach>
反而。它在视图构建期间运行,生成 JSF 组件树。然后,您最终会得到子组件的物理多个实例,这些实例又会生成各自的 HTML 输出,而不会被多次重用。
由于前面提到的原因,建立一个小组并试图找到所有孩子显然是行不通的。这<ui:repeat>
不会在组件树中生成物理上的多个 JSF 组件。相反,它根据当前迭代轮的状态重复使用相同的组件来多次生成 HTML 输出。
替换为<c:forEach>
应该有效。也许您遇到了计时问题,因为它在视图构建期间运行,而您正在准备模型,例如preRenderView
代替@PostConstruct
or so.
如果您仔细阅读以上内容,就更容易理解JSF2 Facelets 中的 JSTL...有意义吗?
至于您的具体功能要求,您通常会使用Validator
为了工作。如果您在输入组件上注册它,那么它将在每个迭代轮中被调用。您将立即拥有正确的输入组件和正确的状态作为第二个参数validate()
方法和提交/转换的值作为第三个参数。
如果您确实需要事后执行该工作,例如因为您需要了解所有输入,那么您应该以编程方式迭代<ui:repeat>
你自己。你可以在以下的帮助下做到这一点UIComponent#visitTree()这允许您收集每个迭代轮次的输入组件的状态。
E.g.
final FacesContext facesContext = FacesContext.getCurrentInstance();
UIComponent repeat = getItSomehow(); // findComponent, binding, etc.
repeat.visitTree(VisitContext.createVisitContext(facesContext), new VisitCallback() {
@Override
public VisitResult visit(VisitContext context, UIComponent target) {
if (target instanceof UIInput && target.getId().equals("theTitle")) {
String clientId = target.getClientId(facesContext);
Object value = ((UIInput) target).getValue();
// ...
facesContext.addMessage(clientId, message);
}
return VisitResult.ACCEPT;
}
});
也可以看看: