我有一个数据表,我想将每一行的id设置为构建表的数组中当前项(具有id字段的对象)的id。
的例子:
<h:dataTable
value="#{bean.list}"
var="item">
<h:column>
<h:outputText id="#{item.id}" .... />
</h:column>
</h:dataTable>
这不能工作,因为我得到:javax.servlet.ServletException: Empty id attribute is not allowed
.
是不可能这样设置id由于JSF如何构建它的id,还是我做错了什么?
从JSF UI组件,id
和binding
属性是在视图构建时评估的,当XHTML/JSP文件中的XML树结构被解析并转换为JSF组件树时,FacesContext#getViewRoot()
可用。然而,<h:dataTable>
在视图呈现期间迭代,即JSF组件树需要通过UIViewRoot#encodeAll()
生成HTML代码的时刻。因此,在计算id
属性的那一刻,#{item}
在EL作用域中无处可用,并计算为null
,最终打印一个空字符串。
基本上有3种解决方案:
-
使用像JSTL
<c:forEach>
这样的视图构建时间标签,以便#{item}
在视图构建时间期间也可用。<table> <c:forEach items="#{bean.list}" var="item"> <tr><td><h:outputText id="#{item.id}" ... />
参见JSF2 Facelets中的JSTL…有道理吗?
-
不要把它打印成JSF组件的ID,而是普通HTML元素的ID。
<span id="#{item.id}">
请注意,根据HTML规范6.2章,以数字开头的id在HTML中是无效的。你可能想用一些字符串作为前缀,像这样:
<span id="item_#{item.id}">
-
不要使用动态ID。只需使用固定ID。无论如何,JSF都会根据行索引自动生成一个唯一的ID。
<h:outputText id="foo" ... />
如果它位于
<h:form id="formId"><h:dataTable id="tableId">
内,则最终会出现在<span id="formId:tableId:0:foo">
中。0
是基于0的行索引,每一行递增。这样就保证了在每一行中都有一个唯一的ID,而不需要自己担心。
不能这样在id
属性中使用EL。id
属性应该在视图构建时可用,但在视图呈现时评估EL。这太迟了,所以当id
被选中时,它是空的。