Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Date range validation

I want to compare two dates (StartDate and EndDate) and check whether one is before the other. The simplest solution is to just do it on the backing bean and "short-circuit" the method.

However this validation does not happen concurrently with the other form validations. For example if I have another field that requires validation (besides the dates) and has invalid input, I will only get a message for that specific field. Only if the other fields are valid will I get the date validation based on the backing bean.

Anyone have a solution?

like image 657
ChrisGeo Avatar asked Sep 30 '13 11:09

ChrisGeo


People also ask

What is a date validation?

Sample 1Sample 2. date of validation means the date when the Referred Party has successfully validated his/her identity and fully completed the on-boarding procedures.

How do I limit a date range in Excel?

To do this, first select the cells you want to restrict. Then, go to Data > Data Tools > Data Validation. In the Allow box, select "Date" from the drop-down menu. Then, in the Data box, enter the minimum and maximum dates you want to allow.


1 Answers

However this validation does not happen concurrently with the other form validations.

A backing bean action method is indeed not intented to perform input validation.


Anyone have a solution?

Use the right tool for the job; use a normal Validator.

@FacesValidator("dataRangeValidator")
public class DateRangeValidator implements Validator {
    // ...
}

Validating multiple input values with a single validator is in turn however indeed a story apart. Basically, you should be grabbing/passing the other component or its value along into the validate() method implementation. In its simplest form, you could use <f:attribute> for this. Assuming that you're using <p:calendar> to pick dates, here's a concrete kickoff example:

<p:calendar id="startDate" binding="#{startDateComponent}" value="#{bean.startDate}" pattern="MM/dd/yyyy" required="true" />
<p:calendar id="endDate" value="#{bean.endDate}" pattern="MM/dd/yyyy" required="true">
    <f:validator validatorId="dateRangeValidator" />
    <f:attribute name="startDateComponent" value="#{startDateComponent}" />
</p:calendar>

(note the binding attribute, it makes the component available in the EL scope on exactly the given variable name; also note that this example is as-is and that you should absolutely not bind it to a bean property!)

Where the dateRangeValidator look like this:

@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));
        }
    }

}

If you happen to use JSF utility library OmniFaces, then you could also just use its <o:validateOrder> component. The requirement can be achieved as follows without the need for a custom validator:

<p:calendar id="startDate" value="#{bean.startDate}" pattern="MM/dd/yyyy" required="true" />
<p:calendar id="endDate" value="#{bean.endDate}" pattern="MM/dd/yyyy" required="true" />
<o:validateOrder components="startDate endDate" />

See also:

  • JSF doesn't support cross-field validation, is there a workaround?
like image 53
BalusC Avatar answered Nov 11 '22 22:11

BalusC