Set id of a component within JSF dataTable to value from current item in the array

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:

  1. 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?

  2. 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}">
    
  3. 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.


You can't use EL in id attribute in this way. id attribute should be available during view build time but your EL is evaluated during view render time. This is too late, so in moment when id is checked it is empty.