JSF2 EL does not appear in component identifiers

I have the following code snippet:

<ui:repeat var = "ctr" value = "#{bean.counterList}"> <h:outputLabel for = "message#{ctr}" value = "#{appMessage['No #{ctr} :" /> <h:inputText id="message#{ctr}" value="#{bean.messageList}" /> </ui:repeat> 

counterList is a List<String> . If the list contains 1, 2, 3 , in the view you should have 3 input fields with identifiers: message1, message2, message3 .

EL does not affect the id attribute, and all components receive only the message as an identifier. On the other hand, in the label value, EL works fine.

I can imagine that this may be the desired behavior, but is there a workaround?

UPDATE:

I removed the id attribute, and ui:repeat is responsible for naming the identifier. From the source code, I see that the generated identifier is unique, but now this warning is issued:

 INFO: WARNING: FacesMessage(s) have been enqueued, but may not have been displayed. sourceId=fm-story:j_idt103:0:j_idt54[severity=(ERROR 2), summary=(Conversion Error setting value '' for 'null Converter'.), detail=(Conversion Error setting value '' for 'null Converter'.)] sourceId=fm-story:j_idt103:1:j_idt54[severity=(ERROR 2), summary=(Conversion Error setting value '' for 'null Converter'.), detail=(Conversion Error setting value '' for 'null Converter'.)] 
+4
source share
4 answers

You should not try to manually index component identifiers inside a full-fledged iterative JSF component, such as <ui:repeat> , <h:dataTable> , etc. This will only lead to disaster, as you survived. It will work inside the JSTL <c:forEach> , because it works as a presentation time tag at the time the JSF component tree was created, and not at the time the HTML output was created. <c:forEach> also physically generates as many JSF components as it did.

Just omit any EL from the id attribute. The JSF component will worry about setting the correct client ID automatically. Alternatively, you can use the varStatus <ui:repeat> attribute to get the current loop counter and index. This way you do not need 2 lists. The score will show the current round. An index is required in order to get / set the value of a List<String> by index. <h:inputText value="#{message}" /> will not work because the String class does not have an installer.

 <ui:repeat value="#{bean.messageList}" var="message" varStatus="loop"> <h:outputLabel for="message" value="#{appMessage['No']} #{loop.count}:" /> <h:inputText id="message" value="#{bean.messageList[loop.index]}" /> </ui:repeat> 

(if necessary, you can omit var="message" from the above snippet, since it is not used anywhere)

0
source

I have not tested it, but the correct behavior will be:

 <ui:repeat var = "ctr" value = "#{bean.counterList}"> <h:outputLabel for="message" value="#{appMessage['No #{ctr} :" /> <h:inputText id="message" value="#{bean.messageList}" /> </ui:repeat> 

The identifier of the message component does not change; the client identifier (for example, fm-story:j_idt103:0:message ) will change on each line during life cycle processing. The for tag label component attribute algorithm will be able to find the input component using a "message" because they share a naming container.

+2
source

the same thing that I had ... How to set the id h: panelGroup inside ui: repeat

you cannot set identifiers in a fly using ui: repeat (see link above)

You can use <c:forEach

like this

 <c:forEach var = "ctr" items = "#{bean.counterList}"> <h:outputLabel for = "message#{ctr}" value = "#{appMessage['No #{ctr} :" /> <h:inputText id="message#{ctr}" value="#{bean.messageList}" /> </c:forEach> 

(BUT you should be well aware of how JSTL works in Facelets)

+1
source

Source: https://habr.com/ru/post/1397566/


All Articles