我究竟做错了什么
以非标准的JSF方式在数据表的上下文之外执行验证。仅 当
您(或JSF)在数据表上迭代时,行数据才可用。实际上
<p:calendar>,每列中只有一个组件具有多个不同的状态,具体取决于当前的数据表迭代回合。当您不遍历数据表时,这些状态不可用。然后,您只会获得
null价值。
从技术上讲,到目前为止,您使用不同的验证方法,您应该
visitTree()在
UIData组件上调用方法并在
VisitCallback实现中执行工作。这将遍历数据表。
例如,
dataTable.visitTree(VisitContext.createVisitContext(), new VisitCallback() { @Override public VisitResult visit(VisitContext context, UIComponent component) { // Check if component is instance of <p:calendar> and collect its value by its ID. return VisitResult.ACCEPT; }});这只是笨拙。这为您提供了每一行,您需要自己维护和检查行索引并收集值。注意,调用
UIInput#setValid()也应该在实现内部完成
VisitCallback。
还是我应该使用完全不同的策略?
是的,请使用标准
Validator的标准JSF方法。您可以将一个组件作为另一组件的属性来传递。
例如
<p:column> <p:calendar binding="#{startDateComponent}" id="startDate" required="true" value="#{item.start}" pattern="MM/dd/yyyy hh:mm a"/></p:column><p:column > <p:calendar id="endDate" required="true" value="#{item.end}" pattern="MM/dd/yyyy hh:mm a"> <f:validator validatorId="dateRangevalidator" /> <f:attribute name="startDateComponent" value="#{startDateComponent}" /> </p:calendar></p:column>与
@FacesValidator("dateRangevalidator")public class DateRangevalidator implements Validator { @Override public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException { if (value == null) { return; // Let required="true" handle. } UIInput startDateComponent = (UIInput) component.getAttributes().get("startDateComponent"); if (!startDateComponent.isValid()) { return; // Already invalidated. Don't care about it then. } Date startDate = (Date) startDateComponent.getValue(); if (startDate == null) { return; // Let required="true" handle. } Date endDate = (Date) value; if (startDate.after(endDate)) { startDateComponent.setValid(false); throw new ValidatorException(new FacesMessage( FacesMessage.SEVERITY_ERROR, "Start date may not be after end date.", null)); } }}由于两个组件都在同一行中,因此每次调用此验证器时,
startDateComponentwill都会自动“自动”提供正确的值
getValue()。请注意,该验证器在数据表外部也可以重用,而您的初始方法则不是。
或者,您可以将OmniFaces
<o:validateOrder>用作完整的解决方案。它的展示实例甚至展示
<p:calendar>了
<p:dataTable>。



