I recently brought the OmniFaces library into my project to make use of its Ajax utility, but since having done that, my PrimeFaces editable datatable is now ignoring validation errors.
I currently have a p:datatable with a custom validator and filter like so:
<p:dataTable var="ticket" value="#{myBean.tickets}"
id="ticketTable" widgetVar="ticketTable" editable="true"
rowKey="#{ticket.idTicket}"
filteredValue="#{myBean.filteredTickets}"
paginator="true" rows="20"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="#{myBean.rowsPerPageTemplate}">
<p:ajax event="rowEdit" listener="#{myBean.onEdit}"
/>
<p:ajax event="rowEditCancel"
listener="#{myBean.onCancel}" />
<p:column headerText="Title" sortBy="#{ticket.title}"
filterBy="#{ticket.title}">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{ticket.title}" />
</f:facet>
<f:facet name="input">
<p:inputText value="#{ticket.title}" />
</f:facet>
</p:cellEditor>
</p:column>
<p:column sortBy="#{ticket.start}">
<f:facet name="header">
<h:panelGrid columns="1">
<h:outputText value="Start" />
<h:panelGrid columns="3">
<h:outputLabel value="From:" for="filterTripDateFrom" />
<p:calendar id="filterTripDateFrom"
value="#{myBean.filterStart}" navigator="true"
effect="fadeIn" pattern="MM/dd/yy" size="8">
<p:ajax event="dateSelect"
listener="#{myBean.filterDates()}"
update="ticketTable" />
</p:calendar>
<p:commandButton value="Clear"
action="#{myBean.clearStart()}"
update="filterTripDateFrom, ticketTable" />
</h:panelGrid>
</h:panelGrid>
</f:facet>
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{ticket.start}">
<f:convertDateTime pattern="EE, MMM dd, yyyy: HH:mm z" />
</h:outputText>
</f:facet>
<f:facet name="input">
<p:calendar value="#{ticket.start}" pattern="MM/dd/yy HH:mm"
stepMinute="15">
<f:validator validatorId="dateValidator" />
<f:attribute name="endDate"
value="#{editEndDate}" />
</p:calendar>
</f:facet>
</p:cellEditor>
</p:column>
<p:column sortBy="#{ticket.end}">
<f:facet name="header">
<h:panelGrid columns="1">
<h:outputText value="End" />
<h:panelGrid columns="3">
<h:outputLabel value="To:" for="filterTripDateTo" />
<p:calendar id="filterTripDateTo"
value="#{myBean.filterEnd}" navigator="true"
effect="fadeIn" pattern="MM/dd/yyyy" size="8">
<p:ajax event="dateSelect"
listener="#{myBean.filterDates()}"
update="ticketTable" />
</p:calendar>
<p:commandButton value="Clear"
action="#{myBean.clearEnd()}"
update="filterTripDateTo, ticketTable" />
</h:panelGrid>
</h:panelGrid>
</f:facet>
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{ticket.end}">
<f:convertDateTime pattern="EE, MMM dd, yyyy: HH:mm z" />
</h:outputText>
</f:facet>
<f:facet name="input">
<p:calendar value="#{ticket.end}" pattern="MM/dd/yyyy HH:mm"
stepMinute="15" binding="#{editEndDate}" />
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Options" style="width:50px">
<p:rowEditor />
</p:column>
</p:dataTable>
The behavior before adding OmniFaces was that if my custom date validator (provided below) threw a ValidatorException
, the row in the table that was being edited would stay open and the page would display the FacesMessage
from the exception.
After adding the OmniFaces library, the FacesMessage
still displays, but the row in the table is closed as if there was no exception thrown. I have tried using OmniFaces 1.2 & 1.3 SNAPSHOT, and both have the same behavior.
Is there anyway to get back the original functionality, or will I have to remove OmniFaces from my project?
Thank you for your help
addl info: Tomcat 7.0; MyFaces 2.1; PrimeFaces 3.4.1; OmniFaces 1.3 SNAPSHOT 20121027
My custom Date Validator:
public void validate(FacesContext context, UIComponent component,
Object value) throws ValidatorException
{
// get the submitted value for the start date
DateValidator.logger.debug("starting validation");
Date startDate = (Date) value;
// get the bound component that contains the end date
DateValidator.logger.debug("getting UI component");
UIInput endDateComponent = (UIInput) component.getAttributes().get(
"endDate");
// get the value of the bound component
DateValidator.logger.debug("getting second date");
String endDateString = (String) endDateComponent.getSubmittedValue();
// and parse it into a date
DateValidator.logger.debug("converting date");
Date endDate = JodaUtils
.stringToUtil(endDateString, "MM/dd/yyyy HH:mm");
// if either of the submitted values were empty, let the required tag
// take care of it
if (startDate == null || endDate == null)
{
DateValidator.logger.debug("a date was null; start: " + startDate
+ "; end: "
+ endDate);
return;
}
// otherwise if the start time is the same as, or before the end time
else if (startDate.getTime() >= endDate.getTime())
{
DateValidator.logger
.debug("end date was the same as or before start date; start: "
+ startDate + "; end: " + endDate);
// set the bound component as invalid
endDateComponent.setValid(false);
// update the container containing the components to show that the
// fields were invalid
Ajax.update(endDateComponent.getParent().getClientId());
// and send a notification to the front end
throw new ValidatorException(new FacesMessage(
FacesMessage.SEVERITY_ERROR,
"The end time must be after the start time.",
"The end time must be after the start time."));
}
else
{
DateValidator.logger.debug("all clear; start: " + startDate
+ "; end: "
+ endDate);
}
Ajax.update(":form:ticketTable");
}