I have a problem displaying validation errors that are triggered by ui components which are nested inside a dataTable.
Here is the xhtml page, which contains a form with a static upper part, where an address can be entered.
Below that it shows order items where users can enter amounts of items they would like to order. These items are being retrieved from a database table and are diplayed inside a dataTable.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<ui:composition template="../templates/_standard.xhtml">
<ui:define name="pageHeadline">
#{msg['supplies.module_headline']}
</ui:define>
<ui:define name="pageContent">
<h:form id="supplies" styleClass="editForm" rendered="#{!suppliesHandler.sent}">
<h:panelGrid
columns="2"
columnClasses="tdLabel,tdValue"
rowClasses="row"
styleClass="leftPane"
>
<!-- row 1 -->
#{msg['supplies.account']}:
<h:panelGroup>
<h:inputText id="account" value="#{supply.contact.account}" tabindex="1" styleClass="text"/>
<h:message for="account" styleClass="error"/>
</h:panelGroup>
<!-- row 2 -->
#{msg['supplies.company']}:
<h:panelGroup>
<h:inputText id="company" value="#{supply.contact.company}" tabindex="2" styleClass="text"/>
<h:message for="company" styleClass="error"/>
</h:panelGroup>
<!-- row 3 -->
#{msg['supplies.street']}:
<h:panelGroup>
<h:inputText id="street" value="#{supply.contact.street}" tabindex="3" styleClass="text"/>
<h:message for="street" styleClass="error"/>
</h:panelGroup>
<!-- row 4 -->
#{msg['supplies.postcode']}:
<h:panelGroup>
<h:inputText id="postcode" value="#{supply.contact.postcode}" tabindex="4" styleClass="text"/>
<h:message for="postcode" styleClass="error"/>
</h:panelGroup>
<!-- row 5 -->
#{msg['supplies.city']}:
<h:panelGroup>
<h:inputText id="city" value="#{supply.contact.city}" tabindex="5" styleClass="text"/>
<h:message for="city" styleClass="error"/>
</h:panelGroup>
</h:panelGrid>
<h:panelGrid
columns="2"
columnClasses="tdLabel,tdValue"
rowClasses="row"
styleClass="rightPane"
>
<!-- row 2 -->
#{msg['supplies.contact']}:
<h:panelGroup>
<h:inputText id="contact" value="#{supply.contact.contact}" tabindex="6" styleClass="text"/>
<h:message for="contact" styleClass="error"/>
</h:panelGroup>
<!-- row 3 -->
#{msg['supplies.phone']}:
<h:panelGroup>
<h:inputText id="phone" value="#{supply.contact.phone}" tabindex="7" styleClass="text"/>
<h:message for="phone" styleClass="error"/>
</h:panelGroup>
<!-- row 4 -->
#{msg['supplies.email']}:
<h:panelGroup>
<h:inputText id="email" value="#{supply.contact.email}" tabindex="8" styleClass="text">
<f:validator validatorId="com.abc.myproduct.be.ui.validator" />
</h:inputText>
<h:message for="email" styleClass="error"/>
</h:panelGroup>
<!-- row 5 -->
#{msg['supplies.fax']}:
<h:panelGroup>
<h:inputText id="fax" value="#{supply.contact.fax}" tabindex="9" styleClass="text"/>
<h:message for="fax" styleClass="error"/>
</h:panelGroup>
</h:panelGrid>
<div class="spacer"></div>
<h:dataTable id="items"
styleClass="listing_large"
value="#{supply.supplyItems}"
headerClass="heading"
var="item">
<h:column>
<f:facet name="header">
#{msg['supplies.id']}
</f:facet>
<h:outputText value="#{item.supply_id}" />
</h:column>
<h:column>
<f:facet name="header">
#{msg['supplies.amount']}
</f:facet>
<h:inputText value="#{item.amount}" id="amount" styleClass="text" size="3" maxlength="3" style="width:50px"/>
</h:column>
<h:column>
<f:facet name="header">
#{msg['supplies.description']}
</f:facet>
<h:outputText value="#{item.description}" />
</h:column>
</h:dataTable>
<div><br/>
<h:messages globalOnly="true" layout="table" styleClass="error"/>
</div>
<h:panelGrid
columns="1"
columnClasses="tdLabel,tdValue"
rowClasses="row">
<!-- row 2 -->
<h:panelGroup>
<h:commandButton value="#{msg['general.submit']}" action="#{suppliesHandler.submitMessage}" styleClass="button"/>
</h:panelGroup>
</h:panelGrid>
</h:form>
<h:messages globalOnly="true" layout="table" rendered="#{suppliesHandler.sent}"/>
</ui:define>
</ui:composition>
</html>
Validation for the address part of the form works perfect. Only the messages for this part of the form are not being displayed:
<h:dataTable id="items"
styleClass="listing_large"
value="#{supply.supplyItems}"
headerClass="heading"
var="item">
<h:column>
<f:facet name="header">
#{msg['supplies.id']}
</f:facet>
<h:outputText value="#{item.supply_id}" />
</h:column>
<h:column>
<f:facet name="header">
#{msg['supplies.amount']}
</f:facet>
<h:inputText value="#{item.amount}" id="amount" styleClass="text" size="3" maxlength="3" style="width:50px"/>
</h:column>
<h:column>
<f:facet name="header">
#{msg['supplies.description']}
</f:facet>
<h:outputText value="#{item.description}" />
</h:column>
</h:dataTable>
Validation is being carried out through BeanValidation:
public class SupplyItem implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private long supply_id;
private String description;
private int orderNo;
@Transient
@Max(value=200)
private int amount;
/*
* constructor
*/
public SupplyItem() {
super();
}
public long getSupply_id() {
return supply_id;
}
public void setSupply_id(long supply_id) {
this.supply_id = supply_id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getOrderNo() {
return orderNo;
}
public void setOrderNo(int orderNo) {
this.orderNo = orderNo;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
}
It gets actually being validated, however the messages are not being displayed...
12:29:45,860 Information [javax.enterprise.resource.webcontainer.jsf.renderkit] (http--127.0.0.1-8080-2) WARNUNG: FacesMessage(s) wurde(n) in die Warteschlange gestellt, aber möglicherweise nicht angezeigt. sourceId=supplies:items:0:amount[severity=(ERROR 2), summary=(Allowed maximum is 200), detail=(Allowed maximum is 200)] sourceId=supplies:items:1:amount[severity=(ERROR 2), summary=(supplies:items:1:amount: 'a' must be a number consisting of one or more digits.), detail=(supplies:items:1:amount: 'a' must be a number between -2147483648 and 2147483647 Example: 9346)]
Trying to set the id of the input field dynamically in conjunction with a h:message for="" did not work,displaying it through h:messages globalOnly="true" neither.
Any help would be highly appreciated.