I have something to report that I did not realize about custom UI components in JSF (lots of things probably...)
Consider the following scenario: you put a custom component in a af:iterator component. Can you answer the following questions?
- How many instances of your custom component that you included in that af:iterator loop will be created?
- If your component's function is to print a different kind of input field or widget depending on the parametric input given to the component tag, what might you need to do with any attributes in your component?
The answer to 1 is: one. One for each af:iterator. So if your iterator loop brings back 1000 records from the database, it loops 1000 times and "prints" your component 1000 times, but there is ever only one instance of the component.
For question 2...let us say that your component offers the printing of 4 different kinds of components depending on the value of its "type" tag attribute. So in that page you will have 1000 fields printed one for each af:iterator loop. If your component only rendered UIOutput components then it would suffice to have one property in your component class for each type of component.
But we are doing input components, so decode will be involved. That complicates things. JSF will generate a client id for each field that you generate with your component. If it is in the af:iterator loop it will look something like: formname:iteratorname:n:yourcomponentid -- where n is the zero-based loop index of your af:iterator.
On a JSF postback/decode, each field first runs the decode method. Then each field runs the encode methods for the component. In between the decode runs and the encode runs you need to store the submitted value of each component. I used a HashMap with client id as the key, and the component as the value. If you store everything away in decode you will have whatever you need to do the encode when it occurs for the postback.
Hope this helps someone.