JSF 2.0: jak pominąć walidację JSR-303?
Jak pominąć walidację JSR-303 za pomocą JSF, po kliknięciu przycisku?
Trochę długie pytanie, aby wyjaśnić kilka podejść... Rozważmy listę w formie:
<h:form id="form">
<h:commandButton value="Add row">
<f:ajax execute="foo" listener="#{bean.add()}" render="foo" />
</h:commandButton>
<h:dataTable id="foo" var="foo" value="#{bean.foos}">
<h:column>
Name: <h:inputText id="field" value="#{foo.name}" required="true" />
<h:messages for="field" />
</h:column>
<h:column>
<h:commandButton value="Remove">
<f:ajax execute=":form:foo" listener="#{bean.remove(foo)}" render=":form:foo" />
</h:commandButton>
</h:column>
</h:dataTable>
</h:form>
Gdy użytkownik kliknie Dodaj lub Usuń wiersz, akcja powinna zostać wykonana bez walidacji. Problem w tym, że JSF ponownie renderuje całą listę i próbuje ją zweryfikować. Jeśli są zmiany wersji roboczej, które nie sprawdzają poprawności, pojawiają się błędy walidacji i metoda listener nigdy nie jest wywoływana (ponieważ uniemożliwia to nieudana Walidacja). Jednak dodanie immediate="true"
do F: ajax pozwala na wykonanie metody pomimo błędów walidacji. Jednak błędy walidacji nadal występują i są tutaj pokazywane.
Widzę dwie opcje:
1) Użyj immediate= "true" i nie pokazuj błędów walidacji
Dla przycisków bez walidacji, Ustaw immediate= "true", a dla H: messages do:
<h:messages rendered="#{param['SHOW_VALIDATION']}" />
Następnie Ustaw Save-button (który powinien próbować zapisać formularz), aby wysłać ten parametr:
<h:commandButton>
<f:param name="SHOW_VALIDATION" value="true" />
</h:commandButton>
To powoduje walidację, ale komunikaty są po prostu nie pokazywane, chyba że występuje parametr SHOW_VALIDATION
.
2) zadeklarować walidację w faktach warunkowo:
<h:inputText>
<f:validateRequired disabled="#{!param['VALIDATE']}" />
</h:inputText>
I przycisk zapisu:
<h:commandButton>
<f:param name="VALIDATE" value="true" />
</h:commandButton>
Powoduje, że pola są weryfikowane tylko wtedy, gdy występuje parametr VALIDATE
(=po naciśnięciu przycisku Zapisz).
4 answers
Ustaw swoje procedury obsługi zdarzeń jako immediate=true
i wywołaj FacesContext.renderResponse()
przed ich zakończeniem.
UPDATE :
Modyfikacje w formie przykładowej:
<h:form id="form">
<h:commandButton value="Add row">
<!-- Added immediate="true" to call bean.add() before validation phase -->
<f:ajax execute="foo" listener="#{bean.add()}" render="foo" immediate="true"/>
</h:commandButton>
<h:dataTable id="foo" var="foo" value="#{bean.foos}">
<h:column>
Name: <h:inputText id="field" value="#{foo.name}" required="true" />
<h:messages for="field" />
</h:column>
<h:column>
<h:commandButton value="Remove">
<!-- Added immediate="true" to call bean.remove() before validation phase -->
<f:ajax execute=":form:foo" listener="#{bean.remove(foo)}" render=":form:foo" immediate="true"/>
</h:commandButton>
</h:column>
</h:dataTable>
</h:form>
Modyfikacje w kodzie fasoli:
...
public void add() {
// Your add() code
...
// Added FacesContext.renderResponse() call to skip to render response phase
FacesContext.getCurrentInstance().renderResponse();
}
...
public void remove() {
// Your remove() code
...
// Added FacesContext.renderResponse() call to skip to render response phase
FacesContext.getCurrentInstance().renderResponse();
}
...
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
2011-02-02 12:09:42
Możesz wyłączyć walidację bean za pomocą znacznika f: validateBean, który ma atrybut disabled.
Przykład:
<h:inputText value="#{bean.name}">
<f:validateBean disabled="#{anotherBean.flag}"/>
</h:inputText>
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
2011-02-09 02:22:47
Właśnie opublikowaliśmy rozwiązanie tego problemu. Pełny szczegół znajduje się tutaj: http://www.springfuse.com/2011/12/15/skip-jsf-validation-depending-on-action.html
W skrócie, wykorzystuje atrybut wiążący znacznika validateBean. Pozwala to przechwycić metodę walidacji i zdecydować, na podstawie klikniętego przycisku, czy pozwolić jej przejść, czy nie.
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
2011-12-16 14:56:17
Sytuacja: W kodzie strony znajduje się Duży formularz z dużą ilością pól wejściowych. Istnieje kilka przycisków, z których każdy wskazuje na osobną akcję w oddzielnej fasoli.
Rozwiązanie, które zadziałało na mnie...- w kodzie strony: dodaj
immediate="true"
do przycisku i podaj id pól wejściowych, których chcesz użyć w fasoli.
<p:inputText id="someHtmlInputId" maxlength="30" value="#{beanName.attr}" /> <p:commandButton id="someHtmlButtonId" actionListener="#{beanName.doStuff}" value="Button Label" ajax="false" immediate="true"/>
- w metodzie bean
doStuff
get the parameters by the name fragment couse before the input name JSF put some other identyfikatory i wynikowa nazwa parametru mogą wyglądać następująco: someFormId: j_idt54: someHtmlInputId
Map<String, String> params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap(); if (params != null) { for (String k: params.keySet()) if (k.indexOf("someHtmlInputId") != -1) params.get(k); // This is Your input parameter value waiting to be processed ;) }
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
2012-04-03 10:01:47