Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 738
nivis Avatar asked Mar 27 '13 14:03

nivis


Video Answer


2 Answers

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.

like image 143
BalusC Avatar answered Sep 28 '22 10:09

BalusC


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.

like image 33
partlov Avatar answered Sep 28 '22 11:09

partlov