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.
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>
.
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):
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