如何在ui:repeat中设置组件/标记的ID

12

我试图给一个在 <ui:repeat> 中的组件分配一个 id,像这样:

<ui:repeat value="#{bean.columns}" var="column">
    <h:panelGroup layout="block" id="column_#{column.id}" 
        styleClass="#{column.id} dashboard_column">
问题在于#{column.id}的值已经被正确地放置在了styleClass属性中,但却没有被设置在id属性中。而在id属性中被设置的只有JSF自动生成的id和我的硬编码值column_
如果我移除硬编码的 column_,就会出现异常:

java.lang.IllegalArgumentException: component identifier must not be a zero-length String at

有什么想法吗?
2个回答

16
这是不可能使用渲染时标签(如<ui:repeat>)实现的。然而,<ui:repeat>会自动通过在生成的客户端ID前缀中添加行索引来确保其唯一性。因此,只需从组件的ID属性中删除EL部分即可。
<ui:repeat value="#{bean.columns}" var="column">
    <h:panelGroup layout="block" id="column">

使用诸如<c:forEach>这样的视图构建时标签(它将生成多个<h:panelGroup>组件,而不仅仅是多次呈现一个组件),可以指定动态ID。
<c:forEach items="#{bean.columns}" var="column">
    <h:panelGroup layout="block" id="column_#{column.id}">

你应该只需要清楚JSTL在Facelets中的工作方式。
另一种选择是使用静态的<div>元素,而不是JSF的<h:panelGroup layout="block">组件。
<ui:repeat value="#{bean.columns}" var="column">
    <div id="column_#{column.id}">

参见:


1
谢谢,我最终使用div完成了它。这意味着我不能自己为ui:repeat内的JSF元素分配动态ID?只能为简单的HTML元素分配。 - Daniel
1
没错。渲染时的ID不能在组件树中注册,必须是固定值而不是动态值。无论你想通过这种方式解决什么功能需求,它都不是“JSF-ish”的方式,你可能需要再三考虑以避免未来的意外。 - BalusC

8

JSF会自动添加前缀来区分id。如果你只是简单地写下id="column",生成的HTML将包含如下标识符:

myForm:0:column myForm:1:column myForm:2:column

等等。

无论如何:不要在JSF模板中使用JSTL标签(如c:foreach和c:if)。它们会导致随机行为,非常难以调试。而且,如果它们工作,它们会大大降低应用程序的速度。

使用ui:repeat进行循环,使用ui:fragment进行条件块。请注意,JSF 2中没有c:set的替代方法。


工作得很顺利,解释得非常好。我也想知道为什么它被踩了,但是因为它很有道理,所以我会点赞的。 - Bruno Gasparotto
1
Downvote 是因为这句话:“无论如何,永远不要在 JSF 模板中使用 JSTL 标签(如 c:foreach 和 c:if)。它们会导致随机行为,非常难以调试。而且如果它们能够工作,也会大大降低应用程序的速度。” 这完全不是事实。 - Kukeltje
例如,c:foreachui:repeat不同,它是在编译时确定的,并且不会随着ajax请求而更新。对于上面评论的相反原因加1。 - Marco Sulla

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接