2009-12-21 91 views
8

Trước khi đi vào, nhìn thấy questionLàm cách nào để truy xuất giá trị thành phần JSF bằng cách sử dụng EL?

Đó là hình thức JSF này được thể hiện một lần nữa như sau:

<f:view> 
    <h:form> 
     <div> 
      <label>Id</label> 
      <input type="text" name="accountId"/> 
     </div> 
     <div> 
      <label>Amount</label> 
      <input type="text" name="amount"/> 
     </div> 
     <h:commandButton value="Withdraw" action="#{accountService.withdraw(param.accountId, param.amount)}"/> 
    </h:form> 
</f:view> 

Chú ý rằng tôi đã sử dụng <input type="text" name="amount"> thay vì <h:inputText id="amount">. Để lấy giá trị bằng cách sử dụng trình giải quyết Seam EL, tôi sử dụng param.amount.

Điều đó xảy ra nếu tôi sử dụng <input type="text" và xảy ra sự cố ở phía máy chủ, tôi cần hiển thị lại trang. Vì vậy, giá trị đã gửi của nó không được truy xuất vì đó là một mã html thuần túy. Do đó, tôi cần sử dụng thành phần JS2 <h:inputText JSF thay thế.

Vì vậy, câu hỏi đặt ra là: Làm cách nào để truy xuất giá trị thành phần <h:inputText JSF bằng cách sử dụng Ngôn ngữ biểu thức?

+0

Để bắt đầu, câu hỏi của bạn là khá khó hiểu. Có vẻ như câu chuyện Seam hoàn toàn không có liên quan ở đây. Trong tương lai, hãy đăng mã JSF mà bạn ** thực sự ** có và cho biết chính xác bạn muốn làm gì với ** mã ** của bạn. – BalusC

+0

Điều này cũng không có ý nghĩa. Trong JSP/Servlet đơn giản, bạn có thể đã sử dụng '' cho điều đó. – BalusC

+0

Tôi đặc biệt khuyên bạn nên tự mình trải qua một cuốn sách/hướng dẫn JSF phong nha để hiểu cách JSF hoạt động "dưới mui xe". Ngoài ra học tập "plain vanilla" JSP/Servlet sẽ giúp rất nhiều trong việc hiểu nó. Bạn đang đưa ra các giả định và đang cố gắng phá vỡ ý thức hệ của JSF bằng cách lấy tất cả công việc của nó trên tay bạn. Xin lỗi nếu tôi âm thanh khắc nghiệt, nhưng đó là sự thật. – BalusC

Trả lời

18

ID khách hàng JSF được thêm vào trước bởi ID của bạn bè UINamingContainer thành phần (ví dụ: h:form, h:dataTable, f:subview). Nếu bạn kiểm tra nguồn HTML được tạo trong trình duyệt web của bạn (rightclick, view source), thì bạn sẽ thấy chúng. Các yếu tố idname của các yếu tố đầu vào được tạo được thêm vào trước với id của biểu mẫu gốc. Bạn cần sử dụng cùng tên với khóa trong bản đồ tham số. Vì ký tự dấu tách, dấu hai chấm :, là ký tự "bất hợp pháp" trong EL, bạn cần sử dụng ký hiệu dấu ngoặc đơn param['foo:bar'] để truy xuất chúng.

<f:view> 
    <h:form id="account"> 
     <div> 
      <label>Id</label> 
      <h:inputText id="id" /> 
     </div> 
     <div> 
      <label>Amount</label> 
      <h:inputText id="amount" /> 
     </div> 
     <h:commandButton value="Withdraw" 
      action="#{accountService.withdraw(param['account:id'], param['account:amount'])}"/> 
    </h:form> 
</f:view> 

Nếu không có thông số phương pháp Seam-EL-tương tự (bạn dường như không muốn/có nó), bạn cũng có thể truy cập chúng trên bản đồ theo yêu cầu thông số bằng cách sử dụng ID của khách hàng như phím:

public void withDraw() { 
    Map<String, String> map = FacesContext.getCurrentInstance().getRequestParameterMap(); 
    String id = map.get("account:id"); 
    String amount = map.get("account:amount"); 
    // ... 
} 

Không cần phải nói rằng điều này là khó chịu. Chỉ cần làm điều đó theo cách JSF bình thường, liên kết các giá trị với các thuộc tính bean.

Edit: theo câu hỏi cuối cùng mà bạn đã chỉnh sửa:

Vì vậy, câu hỏi là: làm thế nào để tôi lấy một giá trị thành phần <h:inputText JSF bằng cách sử dụng Expression Language?

Điều này đã được trả lời trước đó. Sử dụng tên JSF tạo làm tên thông số. Điều này thường có dạng là formId:inputId trong đó formIdid của thành phần chính là UIForminputIdid của thành phần UIInput. Kiểm tra đầu ra HTML được tạo cho tên chính xác của trường được tạo ra <input type="text">. Để có được giá trị tham số, sử dụng ký hiệu cú đúp ['name'], vì bạn không thể sử dụng dấu hai chấm : trong EL như trong ${param.formId:inputId}.

Như vậy:

#{param['formId:inputId']} 
+0

Hm, đây là câu trả lời của riêng bạn và điều này có nghĩa vụ phải làm việc? Vâng, tôi chỉ có thể gợi ý để kiểm tra đầu ra HTML được tạo ra để xem các tên có đúng hay không hoặc nếu chúng có sẵn trong bản đồ tham số yêu cầu. – BalusC

+0

Vì vậy, bạn đang nói rằng bạn * thực sự * có một 'h: inputText' trong trang JSF của bạn chứ không phải là ''? Bằng cách này, bạn cần cung cấp cho nó (và biểu mẫu gốc) một 'id' và lấy tham số với ID khách hàng được tạo làm khóa. Tôi sẽ sớm trả lời câu trả lời của tôi. – BalusC

+0

Chúng nằm trong bản đồ tham số yêu cầu. Ví dụ bạn đã sửa lỗi nội dung của nó? 'System.out.println (requestParameterMap);' để bạn có thể nhìn thấy chúng và các mẫu? – BalusC

1

Tên tham số/id cho inputText được đóng gói bởi các renderer kiểm soát và cuối cùng là một chi tiết thực hiện. Trong thực tế, họ sử dụng clientId. Không cần phải đọc chúng trực tiếp từ bản đồ tham số; sử dụng giá trị ràng buộc để đẩy chúng vào mô hình và đọc chúng từ đó.

Bạn có thể đọc các giá trị trực tiếp từ thành phần bằng EL bằng cách liên kết thành phần với bean được quản lý. Để đơn giản, đây là một ràng buộc với phạm vi yêu cầu:

<!-- bind a UIComponent to the request map as "foo" --> 
<h:inputText binding="#{requestScope.foo}" /> 
<!-- read value from a UIComponent that implements ValueHolder --> 
#{requestScope.foo.value} 

Nhưng, nói chung, không có lợi thế này trên:

<!-- bind a value to the request map as "foo" --> 
<h:inputText value="#{requestScope.foo}" /> 
<!-- read value from the request scope --> 
#{requestScope.foo} 

Để tránh gây ô nhiễm bản đồ theo yêu cầu (mà có thể dẫn đến va chạm trên xem), sử dụng bean được quản lý để không gian tên/đóng gói các giá trị của bạn thay vì sử dụng phạm vi yêu cầu trực tiếp.

+0

Tốt insigth, MCDowell. (+1) –

0

Mặc dù tôi có thể lấy giá trị thành phần JSF thông qua nhận dạng của khách hàng, còn có một số nhược điểm như sau:

  1. Theo câu trả lời của McDowell, Từ định danh khách hàng là một chi tiết thực hiện
  2. Từ định danh khách hàng có thể khác nhau từ số nhận dạng thành phần khi có nhiều hơn một vùng chứa tên trong hệ thống phân cấp điều khiển. (JSF trong Action cuốn sách)

Vì vậy, nếu bạn không muốn dựa vào nhận diện khách hàng, bạn có thể thực hiện ElResolver của bạn như sau:

public class ComponentIdResolver extends ELResolver { 

    public Object getValue(ELContext context, Object base, Object property) { 
     if (base instanceof UIComponent && property instanceof String) { 
      UIComponent r = ((UIComponent) base).findComponent((String) property); 

      if (r != null) { 
       context.setPropertyResolved(true); 

       return r; 
      } 
     } 

     return null; 
    } 

} 

Bây giờ tôi có thể sử dụng một cái gì đó tương tự (Chú ý rút phương pháp)

<h:inputText id="accountId" /> 
<h:inputText id="amount" /> 
<h:commandButton value="Withdraw" action="#{accountService.withdraw(view.accountId.value, view.amount.value)}"/> 

xem là một đối tượng JSF ngầm (tương tự như FacesContext.getCurrentInstance(). getViewRoot())

Sau đó reg ister ELResolver của bạn như hình dưới đây (faces-config.xml)

<application> 
    <el-resolver>br.com.view.resolver.ComponentIdResolver</el-resolver> 
</application> 

Nếu bạn muốn biết một cái nhìn sâu sắc tốt về ElResolver thấy Extending the Java EE Unified Expression Language with a Custom ELResolver

regards,

Các vấn đề liên quan