JSF doesn't support cross-field validation, is there a workaround?

后端 未结 2 700
慢半拍i
慢半拍i 2020-11-22 09:32

JSF 2.0 only allows you to validate the input on one field, like check to see if it\'s a certain length. It doesn\'t allow you to have a form that says, \"enter city and sta

相关标签:
2条回答
  • 2020-11-22 09:50

    The easiest custom approach I've seen and used as far is to create a <h:inputHidden> field with a <f:validator> wherein you reference all involved components as <f:attribute>. If you declare it before the to-be-validated components, then you can obtain the submitted values inside the validator by UIInput#getSubmittedValue().

    E.g.

    <h:form>
        <h:inputHidden id="foo" value="true">
            <f:validator validatorId="fooValidator" />
            <f:attribute name="input1" value="#{input1}" />
            <f:attribute name="input2" value="#{input2}" />
            <f:attribute name="input3" value="#{input3}" />
        </h:inputHidden>
        <h:inputText binding="#{input1}" value="#{bean.input1}" />
        <h:inputText binding="#{input2}" value="#{bean.input2}" />
        <h:inputText binding="#{input3}" value="#{bean.input3}" />
        <h:commandButton value="submit" action="#{bean.submit}" />
        <h:message for="foo" />
    </h:form>
    

    (please note the value="true" on the hidden input; the actual value actually doesn't matter, but keep in mind that the validator won't necessarily be fired when it's null or empty, depending on the JSF version and configuration)

    with

    @FacesValidator(value="fooValidator")
    public class FooValidator implements Validator {
    
        @Override
        public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
            UIInput input1 = (UIInput) component.getAttributes().get("input1");
            UIInput input2 = (UIInput) component.getAttributes().get("input2");
            UIInput input3 = (UIInput) component.getAttributes().get("input3");
            // ...
            
            Object value1 = input1.getSubmittedValue();
            Object value2 = input2.getSubmittedValue();
            Object value3 = input3.getSubmittedValue();
            // ...
        }
    
    }
    

    If you declare the <h:inputHidden> after the to-be-validated components, then the values of the involved components are already converted and validated and you should obtain them by UIInput#getValue() or maybe UIInput#getLocalValue() (in case the UIInput isn't isValid()) instead.

    See also:

    • Validator for multiple fields (JSF 1.2 targeted)

    Alternatively, you can use 3rd party tags/components for that. RichFaces for example has a <rich:graphValidator> tag for this, Seam3 has a <s:validateForm> for this, and OmniFaces has several standard <o:validateXxx> components for this which are all showcased here. OmniFaces uses a component based approach whereby the job is done in UIComponent#processValidators(). It also allows customizing it in such way so that the above can be achieved as below:

    <h:form>
        <o:validateMultiple id="foo" components="input1 input2 input3" validator="#{fooValidator}" />
        <h:inputText id="input1" value="#{bean.input1}" />
        <h:inputText id="input2" value="#{bean.input2}" />
        <h:inputText id="input3" value="#{bean.input3}" />
        <h:commandButton value="submit" action="#{bean.submit}" />
        <h:message for="foo" />
    </h:form>
    

    with

    @ManagedBean
    @RequestScoped
    public class FooValidator implements MultiFieldValidator {
    
        @Override
        public boolean validateValues(FacesContext context, List<UIInput> components, List<Object> values) {
            // ...
        }
    }
    

    The only difference is that it returns a boolean and that the message should be specified as message attribute in <o:validateMultiple>.

    0 讨论(0)
  • 2020-11-22 10:06

    Apache ExtVal was not mentioned here.

    There are some cross validations in it (among other validations which might be useful):

    https://cwiki.apache.org/confluence/display/EXTVAL/Property+Validation+Usage#PropertyValidationUsage-CrossValidation

    0 讨论(0)
提交回复
热议问题