13

カスタムISO日時を作成しましたConverter

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

そして、私は次のビューのようにを使用しConverterます<mh:IsoDateTimeConverter>

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

問題は、このビューを最初に開いたときに、すべてのプロパティがConverterクラスに1回だけ設定され、データテーブルが初期プロパティに基づいて値をレンダリングおよび変換することです。

プロパティは行ごとに設定されることを期待していました。どうすればこれを達成できますか?

4

2 に答える 2

26

要するに、データ テーブル行がレンダリングされるたびに、コンバーターのプロパティが設定されることを期待していました。これは事実ではありません。JSF は、ビューが作成されるときに、コンポーネントごとに 1 つのコンバーター インスタンスのみを作成します。行がレンダリングされるたびにコンバーターを作成/リセットすることはありません。

それを機能させるにはいくつかの方法があります。

  • <f:attribute>コンポーネントの時点で動的属性を渡し、Converterその上でインターセプトを許可します。ここで例を見つけることができます: JSF convertDateTime with timezone in datatable。これは、次のように使用できます。

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

  • の代わりに EL 関数を使用しConverterます。ここで例を見つけることができます: Facelets and JSTL (Converting a Date to a String for use in a field)。これは、次のように使用できます。

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

  • コンバーターとデータテーブルDataModelを同じマネージド Bean のプロパティとしてバインドします。このようにして、行データを返す前に、行データに基づいてコンバーターのプロパティを設定できます。以下は、標準の JSF コンポーネントと標準に基づいた基本的なキックオフの例ですDateTimeConverter(PrimeFaces コンポーネントでもカスタム コンバーターでも同様に機能するはずです)。

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

    @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;
        }
    
    }
    

    (クラスは、2 つのプロパティとItemを持つ単なる Bean です)Date dateString pattern

    これにより、

    2011年 9 月 23 日
    2011年 9 月 23 日 2011
    年 9 月 23 日


  • 代わりにOmniFaces を使用してください<o:converter>。属性で EL のレンダリング時間評価をサポートします。ショーケースの<o:converter>も参照してください。

    <h:outputText value="#{item.balanceDate}">
        <o:converter converterId="isoDateTimeConverter" pattern="#{item.pattern}" />
    </h:outputText>
    
于 2011-09-23T15:19:45.983 に答える