2011-09-23 63 views
10

tôi đã tạo ra một tùy chỉnh ISO thời gian ngày Converter:Làm thế nào để đặt thuộc tính chuyển đổi cho mỗi hàng của một datatable?

public class IsoDateTimeConverter implements Converter, StateHolder { 

    private Class type; 
    private String pattern; 

    private boolean transientValue = false; 

    public void setType(Class type) { 
     this.type = type; 
    } 

    public void setPattern(String pattern) { 
     this.pattern = pattern; 
    } 

    @Override 
    public Object getAsObject(FacesContext context, UIComponent component, String value) throws ConverterException { 
     if (StringCheck.isNullOrEmpty(value)) { 
      throw new ConverterException("value not specified"); 
     } 

     try { 
      if (IsoDate.class.equals(type)) { 

       if (WebConst.ISO_DATE_NONE.equals(value)) { 
        return IsoDate.DUMMY; 
       } else { 
        //TODO User spezifische TimeZone auslesen 
        return new IsoDate(value, TimeZone.getDefault().getID()); 
       } 

      } else if (IsoTime.class.equals(type)) { 

       if (WebConst.ISO_TIME_NONE.equals(value)) { 
        return IsoTime.DUMMY; 
       } else { 
        //TODO User spezifische TimeZone auslesen 
        return new IsoTime(value, TimeZone.getDefault().getID()); 
       } 

      } else if (IsoTimestamp.class.equals(type)) { 

       if (WebConst.ISO_TIMESTAMP_NONE.equals(value)) { 
        return IsoTimestamp.DUMMY; 
       } else { 
        //TODO User spezifische TimeZone auslesen 
        return new IsoTimestamp(value, TimeZone.getDefault().getID()); 
       } 

      } else { 
       throw new ConverterException("value not convertible"); 
      } 
     } catch (Exception e) { 
      throw new ConverterException(e.getMessage()); 
     } 
    } 

    @Override 
    public String getAsString(FacesContext context, UIComponent component, Object value) throws ConverterException { 
     if (value == null) { 
      throw new ConverterException("value not specified"); 
     } 

     if (IsoDate.class.equals(value)) { 
      IsoDate isoDate = (IsoDate) value; 

      if (isoDate.isDummy()) { 
       return WebConst.ISO_DATE_NONE; 
      } else { 
       //TODO User spezifische TimeZone auslesen 
       return isoDate.toString(pattern, TimeZone.getDefault().getID(), false); 
      } 

     } else if (IsoTime.class.equals(value)) { 
      IsoTime isoTime = (IsoTime) value; 

      if (isoTime.isDummy()) { 
       return WebConst.ISO_TIME_NONE; 
      } else { 
       //TODO User spezifische TimeZone auslesen 
       return isoTime.toString(pattern, TimeZone.getDefault().getID(), false); 
      } 

     } else if (IsoTimestamp.class.equals(value)) { 
      IsoTimestamp isoTimestamp = (IsoTimestamp) value; 

      if (isoTimestamp.isDummy()) { 
       return WebConst.ISO_TIMESTAMP_NONE; 
      } else { 
       //TODO User spezifische TimeZone auslesen 
       return isoTimestamp.toString(pattern, TimeZone.getDefault().getID(), false); 
      } 

     } else { 
      throw new ConverterException("value not convertible"); 
     } 
    } 

    @Override 
    public Object saveState(FacesContext context) { 
     return new Object[]{type, pattern}; 
    } 

    @Override 
    public void restoreState(FacesContext context, Object state) { 
     type = (Class) ((Object[]) state)[0]; 
     pattern = (String) ((Object[]) state)[1]; 
    } 

    @Override 
    public boolean isTransient() { 
     return transientValue; 
    } 

    @Override 
    public void setTransient(boolean transientValue) { 
     this.transientValue = transientValue; 
    } 
} 

Và tôi sử dụng Converter như <mh:IsoDateTimeConverter> trong giao diện sau:

<p:dataTable value="#{imports.list}" var="item"> 
    <p:column> 
     <h:outputText value="#{item.balanceDate}" immediate="true"> 
      <mh:IsoDateTimeConverter type="#{webConst.ISO_DATE_CLASS}" pattern="#{webConst.ISO_DATE_FORMAT}"/> 
     </h:outputText> 
    </p:column> 
</p:dataTable> 

Vấn đề là, khi tôi lần đầu tiên mở quan điểm này, tất cả các thuộc tính được đặt trong lớp Converter của tôi chỉ một lần và sau đó trình kết xuất dữ liệu và chuyển đổi các giá trị dựa trên các thuộc tính ban đầu.

Tôi hy vọng rằng các thuộc tính được đặt trên cơ sở mỗi hàng. Làm thế nào tôi có thể đạt được điều này?

Trả lời

24

Đến thời điểm này, bạn mong đợi rằng các thuộc tính của trình biến đổi được đặt mỗi khi một hàng có thể lập chỉ mục được hiển thị. Điều này thực sự không đúng. JSF sẽ chỉ tạo một cá thể chuyển đổi cho mỗi thành phần khi khung nhìn được xây dựng, nó sẽ không tạo/reset bộ chuyển đổi mỗi khi hàng được hiển thị.

Có một số cách để ứng dụng hoạt động.

  • Vượt qua các thuộc tính năng động như <f:attribute> của các thành phần và để cho các Converter đánh chặn trên đó. Bạn có thể tìm thấy một ví dụ ở đây: JSF convertDateTime with timezone in datatable. Điều này sau đó có thể được sử dụng như

    <h:outputText value="#{item.balanceDate}"> 
        <f:converter converterId="isoDateTimeConverter" /> 
        <f:attribute name="pattern" value="#{item.pattern}" /> 
    </h:outputText> 
    

  • Sử dụng một chức năng EL thay vì một Converter. Bạn có thể tìm thấy ví dụ tại đây: Facelets and JSTL (Converting a Date to a String for use in a field). Điều này sau đó có thể được sử dụng như

    <h:outputText value="#{mh:convertIsoDate(item.balanceDate, item.pattern)}" /> 
    

  • Bind bộ chuyển đổi và DataTable của DataModel như một thuộc tính của bean được quản lý tương tự. Bằng cách này, bạn sẽ có thể thiết lập các thuộc tính của trình biến đổi dựa trên dữ liệu hàng trước khi trả về nó. Dưới đây là một ví dụ Kickoff cơ bản dựa trên các thành phần JSF chuẩn và tiêu chuẩn DateTimeConverter (nó sẽ làm việc tốt như nhau trên PrimeFaces thành phần và với chuyển đổi tùy chỉnh của bạn):

    <h:dataTable value="#{bean.model}" var="item"> 
        <h:column> 
         <h:outputText value="#{item.date}" converter="#{bean.converter}" /> 
        </h:column> 
    </h:dataTable> 
    

    với

    @ManagedBean 
    @ViewScoped 
    public class Bean implements Serializable { 
    
        private List<Item> items; 
        private DataModel<Item> model; 
        private DateTimeConverter converter; 
    
        @PostConstruct 
        public void init() { 
         items = Arrays.asList(
          new Item(new Date(), "dd-MM-yyyy"), 
          new Item(new Date(), "yyyy-MM-dd"), 
          new Item(new Date(), "MM/dd/yyyy")); 
         model = new ListDataModel<Item>(items); 
         converter = new DateTimeConverter(); 
        } 
    
        public DataModel<Item> getModel() { 
         return model; 
        } 
    
        public Converter getConverter() { 
         converter.setPattern(model.getRowData().getPattern()); 
         return converter; 
        } 
    
    } 
    

    (lớp Item là chỉ một hạt có hai thuộc tính Date dateString pattern)

    kết quả này trong

    23-09-2011
    2011-09-23
    09/23/2011


  • Sử dụng OmniFaces<o:converter> để thay thế. Nó hỗ trợ đánh giá thời gian render của EL trong các thuộc tính. Xem thêm the <o:converter> showcase example.

    <h:outputText value="#{item.balanceDate}"> 
        <o:converter converterId="isoDateTimeConverter" pattern="#{item.pattern}" /> 
    </h:outputText> 
    
Các vấn đề liên quan