我有一个输入元素数量可变的表单,如下所示:
<ui:repeat var="_lang" value="#{myBean.languages}">
<h:inputTextarea value="${_lang.title}" id="theTitle" />
<h:messages for="theTitle"/>
</ui:repeat>
当支持 bean 中的某个方法被触发时,我想向 的第二次迭代添加一条消息ui:repeat
,而不是其他的。
我在这里看到了这个问题的不同变体,所有问题似乎都是由于ui:repeat
JSF 组件树中的迭代不可用。
到目前为止我已经尝试过:
h:inputTextarea
将s绑定到Map<String,UIComponent>
bean 中的 a。(a) ...使用...binding="#{myBean.uiMap[_lang.id]}"
(其中_lang.id
是唯一的字符串)。这产生了JBWEB006017: Target Unreachable, ''BracketSuffix'' returned null。(我使用 id 转储了相应的字符串映射,相同的语法在binding
) (b) ... 或使用...binding="#{myBean.uiMap.get()}"
. 这使页面很好,但是当我按下我的方法的按钮时,setter 不会被调用,因此UIComponent
s 永远不会被添加到Map
.将 s 绑定
h:inputTextarea
到 bean 中的一个数组UIComponent[]
,用正确数量的空值预填充它,然后使用行计数器ui:repeat
作为 xhtml 文件中的索引。得到空指针异常,数组的设置器从未被调用,因此数组从未填充实际UIComponent
的 s。将外部绑定
h:panelGroup
到 bean 并尝试在 JSF 树中的子项中递归查找输入元素。只找到一个输入,请参阅上面的“迭代不可用”问题。我还尝试手动替换
ui:repeat
并c:forEach
生成行号(以便它们有望在 JSF 树中可用),但我根本没有得到任何渲染输出。
(注意:目标是显示验证错误消息,但它们必须来自支持 bean。使用f:validator
或类似的,甚至是自定义的,并不是一个真正的选择,因为我需要验证支持 bean 中的数据。 )
坦率地说,我没有想法。这不会那么难吧?
编辑:
对于我的第三次尝试,绑定到外部h:panelGroup
,这是我的 JSF finder 函数:
private List<UIComponent> findTitleComponents(UIComponent node) {
List<UIComponent> found = new ArrayList<UIComponent>();
for (UIComponent child : node.getChildren()) {
if (child.getId().equals("theTitle")) {
found.add(child);
log.debug("have found "+child.getClientId());
} else {
found.addAll(findTitleComponents(child));
log.debug("recursion into "+child.getClientId());
}
}
return found;
}
我在 上调用它,这是.周围的node
绑定。(我正在使用递归,因为我的实时应用程序有一个稍微嵌套的结构)我认为这应该给我所有的“theTitle”文本区域,这样我就可以添加消息和读取我喜欢的属性。唉,该方法只返回一个“theTitle”组件,日志消息显示了原因:UIComponent
h:panelGroup
ui:repeat
在生成页面的 DOM 中,id 类似于“myform:myPanelGroup:0:theTitle”(包括 的迭代计数器ui:repeat
),而 bean 只看到 getClientId() 之类的myform:myPanelGroup:theTitle
- 并且只存在一次,最后一次 (我猜?)迭代。