Two primefaces calendar component validation

jsfjsf-2primefacesvalidation

I've a form in JSF 2 where I'm using a double field to specify a range of dates. The aim of that is not to let the user to pick a first date which is before the second one. So I want to perform a validation before the form is sent, using p:calendar components. What I do is to tie a validator to the second calendar input in order to access the first component internally and compare dates.

Here it is my xhtml page:

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:p="http://primefaces.org/ui">

<h:head />
<h:body>
    <h:form id="date_form">
        <p:calendar id="date1input" value="#{dateTestBean.date1}" />
        <p:calendar value="#{dateTestBean.date2}" validator="dateValidator">
            <f:attribute name="date1" value="#{date1input}" />
        </p:calendar>
        <p:commandButton value="Submit" action="#{dateTestBean.submit}"
            ajax="false" />
    </h:form>
</h:body>
</html>

My managed bean:

@ManagedBean
@ViewScoped
public class DateTestBean {

    private Date date1;

    private Date date2;

    public Date getDate1() {
        return date1;
    }

    public void setDate1(Date date1) {
        this.date1 = date1;
    }

    public Date getDate2() {
        return date2;
    }

    public void setDate2(Date date2) {
        this.date2 = date2;
    }

    public void submit() {
        System.out.println("Submited " + date1 + " " + date2);
    }

}

My validator class:

@FacesValidator(value = "dateValidator")
public class DateValidator implements Validator {

    @Override
    public void validate(FacesContext context, UIComponent component,
            Object value) throws ValidatorException {
        System.out.println(((UIInput) context.getViewRoot().findComponent(
                "date_form:date1input")).getValue());
        UIInput date = (UIInput) component.getAttributes().get("date1");
        System.out.println(date);
        //Will perform date comparison
    }
}

The output I get here sending 2013-10-10 as first date and 2013-10-12 as second one is:

Thu Oct 10 00:00:00 CEST 2013

null

Submited Thu Oct 10 00:00:00 CEST 2013 Sat Oct 12 00:00:00 CEST 2013

Which suggests f:attribute tag is not working for p:calendar component as it does for other input components. However, I can access the first calendar via view root, but enforces me to know the entire path of the client id of the component I want to validate. Both values are set in the managed bean later with no issues.

A workaround would be to use an ajax call when first date changes in order to place it in the model and send it as date itself in the f:attribute instead of sending the UIInput (I'm already doing it that way).

Isn't there a better way? Perhaps I have to join them in a single component like in this case?

Best Answer

From your code,

<p:calendar id="date1input" ... />
<p:calendar ...>
    <f:attribute name="date1" value="#{date1input}" />
</p:calendar>

The #{date1input} isn't represented by id="date1input". As shown on those code examples, it's represented by binding="#{date1input}".

Fix it accordingly:

<p:calendar binding="#{date1input}" ... />
<p:calendar ...>
    <f:attribute name="date1" value="#{date1input}" />
</p:calendar>

See also:

Related Topic