I'm having a datatable where I would like to set the id of each row to the id of the current item (object that has an id field) in the array that builds the table.
Example:
<h:dataTable
value="#{bean.list}"
var="item">
<h:column>
<h:outputText id="#{item.id}" .... />
</h:column>
</h:dataTable>
This doesn't work as I get: javax.servlet.ServletException: Empty id attribute is not allowed
.
Is it not possible to set the id this way due to how JSF builds its id's, or am I doing something wrong?
From the JSF UI components, the id
and binding
attributes are evaluated during view build time, the moment when the XML tree structure in the XHTML/JSP file is to be parsed and converted to a JSF component tree as available by FacesContext#getViewRoot()
. However, the <h:dataTable>
iterates during view render time, the moment when the JSF component tree needs to produce HTML code by UIViewRoot#encodeAll()
. So, at that moment the id
attribute is evaluated, the #{item}
is nowhere available in the EL scope and evaluates to null
which ultimately prints an empty string.
There are basiclly 3 solutions:
Use a view build time tag like JSTL <c:forEach>
so that the #{item}
is available during view build time as well.
<table>
<c:forEach items="#{bean.list}" var="item">
<tr><td><h:outputText id="#{item.id}" ... />
See further also JSTL in JSF2 Facelets... makes sense?
Don't print it as ID of a JSF component, but of a plain HTML element.
<span id="#{item.id}">
Please note that IDs starting with a digit are invalid in HTML as per HTML spec chapter 6.2. You might want to prefix it with some string like so:
<span id="item_#{item.id}">
Don't use a dynamic ID. Just use a fixed ID. JSF will autogenerate an unique ID based on row index anyway.
<h:outputText id="foo" ... />
This will end up in like <span id="formId:tableId:0:foo">
provided that it's inside a <h:form id="formId"><h:dataTable id="tableId">
. The 0
is the 0-based row index which increments every row. This thus guarantees an unique ID in every row without the need to worry about it yourself.