2011-01-31 12 views
11

Jak pominąć sprawdzanie fasoli JSR-303 za pomocą JSF, po kliknięciu przycisku?JSF 2.0: Jak pominąć sprawdzanie fasoli JSR-303?

Trochę długie pytanie 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> 

Kiedy użytkownik kliknie dodać lub usunąć wiersz, czynność powinien wykonać bez walidacji. Problem polega na tym, że JSF ponownie renderuje całą listę i próbuje ją zweryfikować. Jeśli istnieją zmiany wersji roboczej, które nie są sprawdzane, występują błędy sprawdzania poprawności i metoda detektora nigdy nie jest wywoływana (ponieważ walidacja zakończona niepowodzeniem uniemożliwia to). Jednak dodanie do f: ajax wartości immediate="true" pozwala na wykonanie metody pomimo błędów sprawdzania poprawności. Jednak błędy sprawdzania poprawności nadal występują i są tutaj wyświetlane.

widzę dwie opcje:

1) stosowanie natychmiastowe = "true" i nie wykazują błędy sprawdzania poprawności

Dla niewalidujący przycisków, ustawić natychmiastowy = "true", a dla h: Komunikaty zrobić:

<h:messages rendered="#{param['SHOW_VALIDATION']}" /> 

Następnie ustaw przycisk Zapisz (które powinny faktycznie spróbuj zapisać formularz), aby wysłać ten parametr:

<h:commandButton> 
    <f:param name="SHOW_VALIDATION" value="true" /> 
</h:commandButton> 

Powoduje to sprawdzenie poprawności, ale komunikaty nie są wyświetlane, chyba że obecny jest parametr SHOW_VALIDATION.

2) Stwierdzenie poprawności w Facelets warunkowo:

<h:inputText> 
    <f:validateRequired disabled="#{!param['VALIDATE']}" /> 
</h:inputText> 

i SAVE-button:

<h:commandButton> 
    <f:param name="VALIDATE" value="true" /> 
</h:commandButton> 

Powoduje to pola do sprawdzania poprawności tylko wtedy, gdy parametr VALIDATE jest obecny (= kiedy Zapisz przycisk został wciśnięty).

Ale te wydają się być hackami. W jaki sposób mogę po prostu użyć JAND-303 Bean Validation, ale pominąć go, gdy zostanie zadeklarowany?

+0

Cóż, nie próbowałem żadnych innych rozwiązań sprawdzających poprawność niż JSR-303 i facelets z JSF. Myślę, że ten problem jest związany z JSF, a nie z JSF-303 - tak jakby zapomnieli "natywnie" obsługiwać pomijanie sprawdzania poprawności w JSF. Wydaje się, że jest w tym dużo zamieszania ... –

Odpowiedz

9

Ustaw swoje programy obsługi zdarzeń jako immediate=true i zadzwoń pod numer FacesContext.renderResponse(), zanim je zamkniesz.

UPDATE:

Modyfikacje w przykładowej postaci:

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

... 
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(); 
} 
... 
+0

Jak to się robi w praktyce? Czy możesz dać przykład? –

+0

Aby było jasne: Wykonanie tej czynności powoduje pomijanie faz JSF o numerze 3-5 (sprawdzanie poprawności procesu, model aktualizacji, wywołanie aplikacji) i przechodzi bezpośrednio do fazy 6 (odpowiedź renderowania). Jest to ok, ponieważ wynik jest trochę taki sam, jak gdyby sprawdzanie poprawności zakończyło się niepowodzeniem w fazie 3, a JSF przejdzie do fazy 6. Popraw mnie, jeśli jest źle. Następnym krokiem byłoby uogólnienie/uszczegółowienie tego, więc wywołanie 'FacesContext.getCurrentInstance() .renderResponse()' nie byłoby potrzebne. Wybór jako zaakceptowaną odpowiedź, dzięki za fajne rozwiązanie! :) –

+1

Próbowałem powyższego i ogólnie to działa dobrze. Mój przypadek jest następujący - używam przycisku polecenia, aby dynamicznie dodawać kilka pól tekstowych do strony. Jeśli użyję opcji 'natychmiast = =" fałsz ", sprawdzanie poprawności strony uniemożliwi aktualizację i nie będzie również wyświetlane. Jeśli użyję 'natychmiast = =" prawda "' i zmodyfikuję niektóre wartości wejściowe przed wykonaniem żądania AJAX, modyfikacje nie zostaną przesłane. Jakieś pomysły, w jaki sposób mogę osiągnąć zarówno odczyt zmienionych danych wejściowych w wywołaniu zwrotnym, jak i nie wyzwalają sprawdzania poprawności w tym samym czasie? Z góry dzięki –

8

można wyłączyć sprawdzanie Bean z tagiem f: validateBean, który ma atrybut wyłączony.

Przykład:

<h:inputText value="#{bean.name}"> 
    <f:validateBean disabled="#{anotherBean.flag}"/> 
</h:inputText> 
+0

To również dobra informacja. Jednak nadal jest to trochę kłopotliwe ustawienie dla każdego pola w formie ... –

+2

Można zawijać wiele komponentów wejściowych za pomocą 'f: validateBean', tak jak pokazano tutaj: http://stackoverflow.com/a/17503608/ 1725096 –

-1

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 oddzielną akcję w osobnym komponencie bean.

Roztwór, który pracował dla mnie ...

  1. W kodzie strony: dodaj immediate="true" do przycisku i zapewnić identyfikator dla pól wejściowych, które 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"/> 
  1. W metodzie fasola doStuff uzyskać parametes prowadzonych przez Couse nazwa fragmentu przed nazwą wejścia JSF umieścić niektóre inne identyfikatory i otrzymaną nazwa parametru może wyglądać tak: 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 ;) 
} 
Powiązane problemy