使用转换器创建复合JSF组件

4

我有一个复合的JSF组件 TimePicker.xhtml,其中包含一个支持组件timePickerComponent,用法如下:

      <mi:timePicker style="display: initial;"
        widgetVar="toTimepickerWidget"
        converter="#{timePickerConverter}"
                            value="#{calendarBean.event.to}" 
      /> 

timePickerConverter 是按照通常的方法创建的:

public class TimePickerConverter implements Converter, Serializable {
    @Override
    public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2)
            throws ConverterException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public String getAsString(FacesContext arg0, UIComponent arg1, Object arg2)
            throws ConverterException {
        // TODO Auto-generated method stub
        return null;
    }
}

我该如何在复合组件中使用这个转换器?

更新:

以下是复合组件的代码:

<cc:implementation componentType="timePickerComponent">
    <h:outputScript name="js/timepicker/timepicker_helper.js" target="head"/>
    <div id="#{cc.clientId}" style="#{cc.attrs.style}">

            <p:inputText id="timepicker"
                    scrollHeight="200"
                    value="#{cc.timeLocal}"  
                    size="5"/>

    </div>
</cc:implementation>

基本上我想要做的是将inputText中的纯文本转换为Date对象,对我来说日期部分无关紧要,我只需要对象的时间部分。顺便说一句,作为临时解决方案,我将使用getConvertedValue,如BalusCComposite component with multiple input fields中所述。但是我想知道如何将此功能委托给外部转换器,就像文章中所述:

通常情况下,不应重写此方法,而应将所有内容委托给默认的JSF转换器机制。


你能添加 TimePicker.xhtml 吗?你实际的问题在哪里? - Smutje
@Smutje,由于公司限制,我无法发布精确的代码片段,因此我发布了具有相同思路的MVCE,谢谢。 - Anatoly
我不太明白,为什么你不像 <p:inputText id="timepicker" ... converter="#{cc.attrs.converter}"/> 一样向 inputText 提供转换器。 - Smutje
如果我们谈论的是简单的复合组件,当然是可能的,但如果我们说的是带有多个输入字段的复合组件呢?多个<p:inputText>?在这种情况下,只有委派转换器才能是一种解决方案。 - Anatoly
1个回答

4
为了使用转换器,您可以在后端组件的getConvertedValue方法中显式调用转换器。转换器可以从组件的converter属性中检索:
@FacesComponent("timePickerComponent")
public class TimePickerComponent extends UIInput implements NamingContainer {

    ...

    @Override
    public Object getSubmittedValue() {
        UIInput hourComp = (UIInput) findComponent("timepicker_hour");
        UIInput minutesComp = (UIInput) findComponent("timepicker_minutes");
        return hourComp.getSubmittedValue() + ":" + minutesComp.getSubmittedValue();
    }

    @Override
    protected Object getConvertedValue(FacesContext context,
            Object newSubmittedValue) throws ConverterException {
        Converter converter = (Converter) getAttributes().get("converter");
        if (converter != null) {
            return converter.getAsObject(context, this, (String) newSubmittedValue);
        } else {
            return newSubmittedValue;
        }
    }

}

查看示例代码: https://github.com/destin/SO-answers/tree/master/SO-composite-jsf-component-with-converter 但是,这种方法的缺点在于JSF组件转换为字符串。据我了解,您的组件由几个子元素组成。它们所有的值都需要转换为字符串(就像我所做的:hourComp.getSubmittedValue() + ":" + minutesComp.getSubmittedValue())。
因此,您可能更喜欢定义自己的TimeConverters层次结构,而不是依赖于JSF组件。这些转换器将能够使用几个参数或某些复杂对象(例如Time)作为源。这些转换器可以以与我所做的完全相同的方式检索。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接