Giving the user a hint about failed validation is essential in form based applications. Though JSF components offer a lot validation functionality there is no such thing as a “failedValidationStyleClass” attribute. However, with a little effort we are able to set a specific error style class for a component that failed the validation.

The base class for all input components is UIInput. UIInput offers the method isValid() which can be accessed via EL using the implicit component object:

<h:inputText value="#{address.country}" required="true" styleClass="#{component.valid?'validation-ok':'validation-failed'}" />

Based on this simple example we can create a composite component that includes a label and shows the validation message for the input component if validation failed.

Here is the composites implementation:

<h:form> <h:panelGrid columns="2"> <comp:labelledInput label="Firstname:" value="#{address.firstName}" required="true" /> <comp:labelledInput label="Lastname:" value="#{address.lastName}" required="true" /> <comp:labelledInput label="Street:" value="#{address.street}" required="true" /> <comp:labelledInput label="Number:" value="#{address.number}" required="true" /> <comp:labelledInput label="ZIP:" value="#{address.zip}" required="true" validatorMessage="Please enter a valid zipcode"> <f:validateLength for="input" minimum="5" maximum="5" /> </comp:labelledInput> <comp:labelledInput label="City:" value="#{address.city}" required="true" /> </h:panelGrid> <h:commandButton value="submit" /> </h:form>

As you can see, validators can be attached to our composite and an optional validator message may be set.

This is what the composite looks like:

<cc:interface> <cc:attribute name="label" /> <cc:attribute name="value" /> <cc:attribute name="required" /> <cc:attribute name="requiredMessage" required="false" default="An input is required"/> <cc:attribute name="validatorMessage" required="false" default="Invalid input"/> <cc:editableValueHolder name="input" targets="input"/> </cc:interface> <cc:implementation> <div class="labelledInput"> <h:outputLabel id="label" value="#{cc.attrs.label}" for="input" styleClass="labelledInput-label" /> <h:inputText id="input" value="#{cc.attrs.value}" required="#{cc.attrs.required}" requiredMessage="#{cc.attrs.requiredMessage}" validatorMessage="#{cc.attrs.validatorMessage}" styleClass="labelledInput-input #{component.valid?'':'validation-failed'}" /> <h:panelGroup id="message" layout="block" styleClass="validation-hint" rendered="#{! cc.findComponent('input').valid}"> <h:message for="input"/> </h:panelGroup> </div> </cc:implementation>

The various parts of the component may be styled using the given css classes. As you can see, the panel containing the messages is rendered conditionally. The expression #{! cc.findComponent('input').valid}" is used to determine if the input component passed or failed the validation.

Conclusion: JSF’s composite components are a powerful feature. The functionality for this labelled input component did not even require a single line of Java code.

Like this: Like Loading...

Related