11

I need to solve my problem with generating dynamic ID for some components in JSF.

Have a look at this example:

<h:outputText id="#{bean.id}" value="#{bean.value}" />

My problem is that I am getting this error:

java.lang.IllegalArgumentException: Empty id attribute is not allowed

The ID of the component is empty when I look at generated HTML output. How is this caused and how can I solve it?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Smolda
  • 882
  • 5
  • 13
  • 34

1 Answers1

22

You are right. I am using it inside datatable.

Then this can happen if the #{bean} represents the currently iterated object as declared in var attribute like so:

<h:dataTable value="#{someBean.beans}" var="bean">
    <h:column>
        <h:outputText id="#{bean.id}" value="#{bean.value}" />

The id (and binding) attribute of a JSF component is evaluated during view build time, that moment when the JSF component tree needs to be composed. However, the #{bean} is only available during view render time, that moment when <h:dataTable> needs to iterate over all objects and generate HTML table rows for each of them. The #{bean} is thus not available during view build time and evaluates to null which ultimately gets EL-coerced to an empty string. And hence the exception java.lang.IllegalArgumentException: Empty id attribute is not allowed.

You've basically 3 options:

  1. Use a view build time tag instead to iterate over a collection. You'd only need to write all HTML boilerplate yourself:

    <table>
        <c:forEach items="#{someBean.beans}" var="bean">
            <tr>
                <td>
                    <h:outputText id="#{bean.id}" value="#{bean.value}" />
    
  2. Use a plain HTML element:

    <h:dataTable value="#{someBean.beans}" var="bean">
        <h:column>
            <span id="#{bean.id}">#{bean.value}</span>
    
  3. Don't set a dynamic ID, but a fixed ID. JSF will ensure of uniqueness in HTML output by prepending it with row index of the table:

    <h:dataTable value="#{someBean.beans}" var="bean">
        <h:column>
            <h:outputText id="id" value="#{bean.value}" />
    

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • 1
    Thanks for your answer. The idea was that I wanted for each column connect tooltip from primefaces which requires the ID to be connected at. – Smolda Jul 30 '11 at 18:16
  • 1
    BalusC: You never had the need for a dynamic ID? Without dynamic ID's how would you use a Reusable facelet tag/component, more than once on a JSF page? – bchetty Sep 05 '12 at 22:04
  • @bch: Give it a fixed ID. E.g. `` with ``. Or make it a composite component. – BalusC Sep 05 '12 at 22:41
  • 1
    you saved my life with the suggestion! Thank you :) – Lule Feb 25 '16 at 16:17