2011-01-31 27 views
11

Làm cách nào để bỏ qua xác thực Bean JSR-303 với JSF, khi một nút được nhấp?JSF 2.0: Làm cách nào để bỏ qua xác thực bean JSR-303?

Một cắn câu hỏi dài để giải thích một vài cách tiếp cận ... Hãy xem xét một danh sách trong một hình thức:

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

Khi người dùng nhấp thêm hoặc xoá hàng, các hành động cần thực hiện mà không cần xác nhận. Vấn đề là, JSF làm lại toàn bộ danh sách và cố gắng xác nhận nó. Nếu có những thay đổi dự thảo không xác thực, lỗi xác thực xảy ra và phương pháp nghe không bao giờ được gọi (khi xác thực không thành công ngăn chặn điều đó). Tuy nhiên, thêm immediate="true" vào f: ajax cho phép phương thức thực thi bất chấp lỗi xác thực. Tuy nhiên, lỗi xác thực vẫn xảy ra và được hiển thị ở đây.

tôi thấy hai lựa chọn:

1) Sử dụng ngay lập tức = "true" và không hiển thị lỗi xác nhận

Đối với không kiểm duyệt các nút, thiết lập ngay lập tức = "true" và cho h: thông điệp làm:

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

Sau đó thiết lập Save-nút (mà thực sự nên cố gắng để lưu các hình thức) để gửi rằng tham số:

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

Điều này làm cho xác thực xảy ra, nhưng thông điệp chỉ đơn giản là không được hiển thị trừ khi có thông số SHOW_VALIDATION.

2) Khai báo xác nhận trong Facelets có điều kiện:

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

Và Lưu-button:

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

Điều này làm cho các lĩnh vực để xác nhận chỉ khi tham số VALIDATE hiện diện (= khi Save-button đã được nhấn).

Nhưng những thứ này có vẻ như là một hacks. Làm cách nào tôi có thể sử dụng Xác thực Bean JSR-303 nhưng bỏ qua khi được khai báo?

+0

Vâng, tôi đã không thử bất kỳ giải pháp xác thực nào khác ngoài JSR-303 và các facelet với JSF. Tôi nghĩ vấn đề này liên quan đến JSF chứ không phải lỗi của JSF-303 - giống như là họ đã quên hỗ trợ "nguyên bản" bỏ qua xác thực trong JSF. Dường như có rất nhiều sự nhầm lẫn xung quanh ... –

Trả lời

9

Đặt trình xử lý sự kiện của bạn là immediate=true và gọi FacesContext.renderResponse() trước khi thoát chúng.

CẬP NHẬT:

Sửa đổi dưới dạng ví dụ của bạn:

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

Sửa đổi trong mã đậu của bạn:

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

Làm thế nào để bạn làm điều đó trong thực tế? Bạn có thể đưa ra một ví dụ không? –

+0

Để làm cho nó rõ ràng: Làm điều này làm cho JSF bỏ qua giai đoạn số 3-5 (quá trình xác nhận hợp lệ, mô hình cập nhật, gọi ứng dụng) và đi trực tiếp đến giai đoạn 6 (trả lời). Điều này là ok, như là kết quả là kinda giống như nếu xác nhận không thành công trong giai đoạn 3 và JSF sẽ bỏ qua đến giai đoạn 6. Sửa chữa cho tôi nếu sai. Bước tiếp theo từ việc này là tổng quát hóa/thành phần hóa điều này để gọi 'FacesContext.getCurrentInstance(). RenderResponse()' sẽ không cần thiết. Chọn làm câu trả lời được chấp nhận, cảm ơn vì giải pháp tốt đẹp! :) –

+1

Tôi đã thử ở trên và nói chung nó hoạt động tốt. Trường hợp của tôi là như sau - Tôi sử dụng nút lệnh để tự động thêm một số hộp văn bản vào trang. Nếu tôi sử dụng 'ngay =" sai ", xác thực trang sẽ ngăn cập nhật và cũng sẽ không hiển thị. Nếu tôi sử dụng 'ngay lập tức =" true "', và sửa đổi một số giá trị đầu vào trước khi thực hiện yêu cầu AJAX, các sửa đổi sẽ không được đệ trình. Bất kỳ ý tưởng làm thế nào tôi có thể đạt được cả hai đọc dữ liệu đầu vào thay đổi trong gọi lại và không kích hoạt xác nhận cùng một lúc? Cảm ơn trước –

8

Bạn có thể vô hiệu hóa các xác nhận đậu với thẻ f: validateBean có thuộc tính bị vô hiệu hóa.

Ví dụ:

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

Đây cũng là thông tin tốt. Tuy nhiên, nó vẫn còn hơi cồng kềnh thiết lập điều này cho mỗi trường trong biểu mẫu ... –

+2

Bạn cũng có thể bao bọc nhiều thành phần đầu vào bằng 'f: validateBean', như được hiển thị ở đây: http://stackoverflow.com/a/17503608/ 1725096 –

2

Chúng tôi vừa công bố một giải pháp cho vấn đề này. Chi tiết đầy đủ ở đây: http://www.springfuse.com/2011/12/15/skip-jsf-validation-depending-on-action.html

Tóm lại, nó tận dụng thuộc tính ràng buộc của thẻ validateBean. Làm như vậy cho phép bạn chặn phương thức xác thực và quyết định, dựa trên nút được nhấp, cho dù bạn có để nó đi qua hay không.

-1

Tình huống: Trong mã trang có một biểu mẫu lớn với nhiều trường nhập. Có một số nút mỗi trỏ đến hành động riêng biệt trong đậu riêng biệt.

Một giải pháp mà làm việc cho tôi ...

  1. Trong mã trang: thêm immediate="true" nút và cung cấp một id cho các lĩnh vực đầu vào mà bạn muốn sử dụng trong hạt cà phê.
<p:inputText id="someHtmlInputId" 
       maxlength="30" 
       value="#{beanName.attr}" /> 


<p:commandButton id="someHtmlButtonId" 
        actionListener="#{beanName.doStuff}" 
        value="Button Label" 
        ajax="false" 
        immediate="true"/> 
  1. Trong phương thức đậu doStuff được parametes bởi couse tên đoạn trước tên đầu vào JSF đặt một số định danh khác và kết quả là tên tham số có thể trông như thế này: 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 ;) 
} 
Các vấn đề liên quan