14

我有一个数据表,我想将每一行的 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

由于JSF如何构建其ID,是否无法以这种方式设置ID,还是我做错了什么?

4

2 回答 2

23

从 JSF UI 组件中,idbinding属性在视图构建时进行评估,此时 XHTML/JSP 文件中的 XML 树结构将被解析并转换为可用的 JSF 组件树FacesContext#getViewRoot()。但是,<h:dataTable>在视图渲染期间进行迭代,此时 JSF 组件树需要通过UIViewRoot#encodeAll(). id因此,在评估属性的那一刻#{item}, EL 范围内无处可用,并且评估null最终打印一个空字符串。

基本上有3种解决方案:

  1. 使用像 JSTL<c:forEach>这样的视图构建时间标记,以便#{item}在视图构建时也可用。

    <table>
        <c:forEach items="#{bean.list}" var="item">
            <tr><td><h:outputText id="#{item.id}" ... />
    

    另请参阅JSF2 Facelets 中的 JSTL... 有意义吗?

  2. 不要将其打印为 JSF 组件的 ID,而是作为纯 HTML 元素的 ID。

    <span id="#{item.id}">
    

    请注意,根据HTML 规范第 6.2 章,以数字开头的 ID 在 HTML 中是无效的。您可能想用一些字符串作为前缀,如下所示:

    <span id="item_#{item.id}">
    
  3. 不要使用动态 ID。只需使用固定 ID。无论如何,JSF 都会根据行索引自动生成一个唯一 ID。

    <h:outputText id="foo" ... />
    

    如果<span id="formId:tableId:0:foo">它在<h:form id="formId"><h:dataTable id="tableId">. 是基于 0的0行索引,每行递增。因此,这保证了每一行中的唯一 ID,而无需自己担心。

于 2013-03-27T14:18:17.307 回答
2

您不能id以这种方式在属性中使用 EL。id属性应该在视图构建期间可用,但您的 EL 在视图渲染期间进行评估。这为时已晚,所以在id检查时它是空的。

于 2013-03-27T14:14:35.447 回答