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

后端 未结 2 703
慢半拍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 field with a wherein you reference all involved components as . 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.

    
        
            
            
            
            
        
        
        
        
        
        
    
    

    (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 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 tag for this, Seam3 has a for this, and OmniFaces has several standard 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:

    
        
        
        
        
        
        
    
    

    with

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

    The only difference is that it returns a boolean and that the message should be specified as message attribute in .

    提交回复
    热议问题