2011-08-19 32 views
12

Đang cố gắng để ra một danh sách các mục trong một DataTable, như thế này:JSF convertDateTime với múi giờ trong DataTable

<t:dataTable value="#{mybean.list}" var="item"> 
     <h:column> 
      <h:outputText value="#{item.time}"> 
       <f:convertDateTime pattern="yyyy-MM-dd HH:mm:ssZ" timeZone="#{item.timeZone}" /> 
      </h:outputText> 
     </h:column> 
</t:dataTable> 

Nó luôn luôn định dạng thời gian trong giờ GMT. Nó hoạt động như mong đợi nếu tôi sử dụng một hằng số chuỗi hoặc một bean không phải là biến datatable (như '# {mybean.timeZone}').

Trả lời

22

Thật không may, đó là bản chất của các thẻ <f:xxx>. Khi khung nhìn được xây dựng, một cá thể của thẻ được xây dựng nơi bộ chuyển đổi được khởi tạo. Tất cả các tài liệu của nó được đọc và chỉ đặt một lần. Tại thời điểm xem được xây dựng, các #{item} giải quyết thành null (chỉ có sẵn khi hiển thị chế độ xem), vì vậy thuộc tính timeZone sẽ là null và sau đó mặc định là UTC. Khi khung nhìn được hiển thị, cá thể chuyển đổi rất giống nhau được tái sử dụng cho mỗi hàng của bảng.

Có một số cách để giải quyết vấn đề này. Tôi có thể nghĩ về một công cụ chuyển đổi tùy chỉnh hoặc một chức năng EL. Tôi nghĩ rằng một bộ chuyển đổi tùy chỉnh là sau khi tất cả các tốt nhất vì nó có thể sau đó cũng được tái sử dụng trong các thành phần đầu vào. Ví dụ Kickoff sau nên làm việc ra cho bạn (nullchecks và bỏ qua cho ngắn gọn):

@FacesConverter("extendedDateTimeConverter") 
public class ExtendedDateTimeConverter extends DateTimeConverter { 

    @Override 
    public Object getAsObject(FacesContext context, UIComponent component, String value) { 
     setPattern((String) component.getAttributes().get("pattern")); 
     setTimeZone(TimeZone.getTimeZone((String) component.getAttributes().get("timeZone"))); 
     return super.getAsObject(context, component, value); 
    } 

    @Override 
    public String getAsString(FacesContext context, UIComponent component, Object value) { 
     setPattern((String) component.getAttributes().get("pattern")); 
     setTimeZone(TimeZone.getTimeZone((String) component.getAttributes().get("timeZone"))); 
     return super.getAsString(context, component, value); 
    } 

} 

mà có thể được sử dụng như

<h:outputText value="#{item.time}"> 
    <f:converter converterId="extendedDateTimeConverter" /> 
    <f:attribute name="pattern" value="yyyy-MM-dd HH:mm:ssZ" /> 
    <f:attribute name="timeZone" value="#{item.timeZone}" /> 
</h:outputText> 

Bằng cách này, múi giờ được giải quyết mọi công cụ chuyển đổi được gọi thay vì trong quá trình xây dựng.


Cập nhật: các OmniFaces <o:converter> giải quyết chính xác vấn đề này mà không cần một bộ chuyển đổi tùy chỉnh.

<h:outputText value="#{item.time}"> 
    <o:converter converterId="javax.faces.DateTime" pattern="yyyy-MM-dd HH:mm:ssZ" timeZone="#{item.timeZone}" /> 
</h:outputText> 
Các vấn đề liên quan