JSF nie obsługuje walidacji między polami, czy istnieje obejście?

JSF 2.0 pozwala zweryfikować dane wejściowe tylko w jednym polu, np. sprawdzić, czy ma określoną długość. Nie pozwala na posiadanie formularza, który mówi: "wprowadź miasto i stan lub wprowadź tylko kod pocztowy."

Jak sobie z tym radzisz? Interesują mnie tylko odpowiedzi, które dotyczą fazy walidacji JSF. Nie jestem zainteresowany umieszczaniem logiki walidacji w Managed Beans.

Author: BalusC, 2011-06-08

2 answers

Najprostszym niestandardowym podejściem, jakie widziałem i używałem do tej pory, jest utworzenie <h:inputHidden> pola z <f:validator>, w którym odwołujesz się do wszystkich zaangażowanych komponentów jako <f:attribute>. Jeśli zadeklarujesz przed składnikami do walidacji, możesz uzyskać przesłane wartości wewnątrz walidatora poprzez UIInput#getSubmittedValue().

Np.

<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>

(zwróć uwagę na value="true" na ukrytym wejściu; rzeczywista wartość w rzeczywistości nie ma znaczenia, ale pamiętaj, że walidator niekoniecznie będzie wywołane, gdy jest puste lub null, w zależności od wersji i konfiguracji JSF)

Z

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

}

Jeśli zadeklarujesz <h:inputHidden> Po komponentach do walidacji, wtedy wartości zaangażowanych komponentów są już przekonwertowane i walidowane i należy je uzyskać przez UIInput#getValue() a może UIInput#getLocalValue() (W przypadku, gdy UIInput nie jest isValid()) zamiast tego.

Zobacz też:


Alternatywnie, można użyć 3rd party tagi / komponenty do tego. RichFaces na przykład ma <rich:graphValidator> tag dla tego, Seam3 mA <s:validateForm> do tego iOmniFaces ma kilka standardowych <o:validateXxx> komponenty do tego, które są wszystkie zaprezentowane tutaj. OmniFaces wykorzystuje podejście oparte na komponentach, dzięki czemu zadanie jest wykonywane w UIComponent#processValidators(). Pozwala równieżdostosować to w taki sposób, aby powyższe można było osiągnąć jak poniżej:

<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>

Z

@ManagedBean
@RequestScoped
public class FooValidator implements MultiFieldValidator {

    @Override
    public boolean validateValues(FacesContext context, List<UIInput> components, List<Object> values) {
        // ...
    }
}

Jedyną różnicą jest to, że zwraca boolean i że wiadomość powinna być określona jako atrybut message w <o:validateMultiple>.

 61
Author: BalusC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55

Apache ExtVal nie wspomniano tutaj.

Są w nim pewne walidacje krzyżowe (między innymi walidacje, które mogą być przydatne):

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

 2
Author: Jens,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-02 08:34:21