O JSF não suporta validação entre campos, existe uma solução alternativa?

O JSF 2.0 só permite validar a input em um campo, como verificar se tem um determinado tamanho. Ele não permite que você tenha um formulário que diga “insira a cidade e o estado ou insira apenas um código postal”.

Como você conseguiu isso? Estou interessado apenas nas respostas que envolvem a fase de validação do JSF. Não estou interessado em colocar lógica de validação em beans gerenciados.

A abordagem personalizada mais fácil que vi e usei até agora foi criar um campo com um em que você referencia todos os componentes envolvidos como . Se você declará-lo antes dos componentes a serem validados, poderá obter os valores enviados dentro do validador por UIInput#getSubmittedValue() .

Por exemplo

              

(observe o value="true" na input oculta; o valor real, na verdade, não importa, mas lembre-se de que o validador não será necessariamente triggersdo quando estiver nulo ou vazio, dependendo da versão e configuração do JSF)

com

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

Se você declarar o após os componentes a serem validados, os valores dos componentes envolvidos já serão convertidos e validados e você deverá obtê-los por UIInput#getValue() ou talvez UIInput#getLocalValue() (em caso o UIInput não é isValid() ).

Veja também:

  • Validador para vários campos (alvo do JSF 1.2)

Como alternativa, você pode usar tags / componentes de terceiros para isso. Por exemplo, o RichFaces tem uma tag para isso, o Seam3 tem um para isso e o OmniFaces tem vários componentes padrão para isso, que são todos exibidos aqui . O OmniFaces usa uma abordagem baseada em componentes, na qual o trabalho é feito no UIComponent#processValidators() . Ele também permite personalizá- lo de tal forma que o acima pode ser alcançado como abaixo:

         

com

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

A única diferença é que ele retorna um boolean e que a mensagem deve ser especificada como atributo de message em .

O Apache ExtVal não foi mencionado aqui.

Existem algumas validações cruzadas (entre outras validações que podem ser úteis):

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