JSF non supporta la convalida cross-field, esiste una soluzione alternativa?

JSF 2.0 consente solo di convalidare l’input su un campo, come il controllo per vedere se è una certa lunghezza. Non ti consente di avere un modulo che dice “inserisci città e stato o inserisci solo un codice postale”.

Come hai capito questo? Mi interessano solo le risposte che riguardano la fase di validazione di JSF. Non sono interessato a mettere la logica di validazione in Managed Beans.

L’approccio personalizzato più semplice che ho visto e utilizzato finora è quello di creare un campo con un cui fai riferimento a tutti i componenti coinvolti come . Se lo si dichiara prima dei componenti da validare, è ansible ottenere i valori inviati all’interno del validatore da UIInput#getSubmittedValue() .

Per esempio

              

(si noti il value="true" sull’input nascosto, il valore effettivo in realtà non ha importanza, ma si tenga presente che il validatore non verrà necessariamente triggersto quando è nullo o vuoto, a seconda della versione e della configurazione JSF)

con

 @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 dichiari dopo i componenti convalidati da to-be, i valori dei componenti coinvolti sono già convertiti e convalidati e dovresti ottenerli da UIInput#getValue() o forse UIInput#getLocalValue() (in caso invece l’ UIInput non è isValid() ).

Guarda anche:

  • Validatore per più campi (target JSF 1.2)

In alternativa, puoi usare tag / componenti di terze parti per questo. Ad esempio, RichFaces ha un tag per questo, Seam3 ha un per questo, e OmniFaces ha diversi componenti standard per questo che sono tutti mostrati qui . OmniFaces utilizza un approccio basato sui componenti in base al quale il lavoro viene eseguito in UIComponent#processValidators() . Permette anche di personalizzarlo in modo tale che quanto sopra può essere raggiunto come di seguito:

         

con

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

L’unica differenza è che restituisce un valore boolean e che il messaggio deve essere specificato come attributo del message in .

Apache ExtVal non è stato menzionato qui.

Vi sono alcune convalide incrociate (tra le altre convalide che potrebbero essere utili):

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