I am trying to validate multiple components in a ui:repeat.
How can I get UIInput from a ui:repeat in the SiteBean?
JSF code is:
<f:event listener="#{siteBean.listenerMyListener}" type="preValidate" />
<ez:inputText id="txtMY" required="true" value="Hallo" />
<ui:repeat
id ="myRepeat"
var="item"
value="#{siteBean.myList}"
varStatus="status">
<ez:panel style="margin-bottom: 7px; #{status.even ? 'background-color: #E6EFC2;' : 'background-color: #e5f1fa;'}">
<h:messages for="hiddenValidation" />
<h:inputHidden id="hiddenValidation" value="" />
<h:outputText value="Rechnung vom:" />
<ez:inputText id="txtDatum" value="#{item.datum}"
style="width: 100px; text-align: right;">
<f:convertDateTime pattern="dd.MM.yyyy" />
</ez:inputText>
<br /><br />
<h:outputText value="Netto:" />
<ez:inputText id="txtNetto" required="true" value="#{item.netto}" style="width: 100px; text-align: right;">
<f:convertNumber pattern="###0.00" />
<f:validateBean />
</ez:inputText>
<br /><br />
<h:outputText value="Brutto:" />
<ez:inputText id="txtBrutto" required="true" value="#{item.brutto}" style="width: 100px; text-align: right;">
<f:convertNumber pattern="###0.00" />
</ez:inputText>
</ez:panel>
</ui:repeat>
Bean code:
public void listenerMyListener(ComponentSystemEvent event) {
FacesContext context = FacesContext.getCurrentInstance();
UIComponent components = event.getComponent();
UIViewRoot viewRoot = FacesContext.getCurrentInstance().getViewRoot();
UIInput search_txtMY = (UIInput) viewRoot.findComponent("frmMY:txtMY");
String value_txtMY = search_txtMY.getLocalValue().toString(); // Hallo
UIInput search_txtDatum = (UIInput) viewRoot.findComponent("frmMY:myRepeat:0:txtDatum"); // NULL
String value_txtDatum = search_txtDatum.getLocalValue().toString(); // java.lang.NullPointerException
}
An
<ui:repeat>is not a view build time tag, but a view render time tag. There’s only one<h:inputText>component in the view tree, identified byfrmMY:myRepeat:txtDatum. It’s however rendered multiple times, as many times as the<ui:repeat>iterates. If you were using<c:forEach>, which is a view build time tag, then there are indeed multiple<h:inputText>components in the view, each which are rendered only one time.You need to solve the problem differently. The
<c:forEach>might not be the right solution as it may have nasty “side effects”, depending on how your entire view and model is designed. As the functional requirement is unclear and the need to collect the input values in a system event listener does not make any sense (I can’t think of any sensible real world applicances of this approach), I can’t suggest anything how to solve it differently and properly. I guess that you just need aValidator.