如何使用自定义渲染器渲染复合组件?

时间:2012-09-21 07:42:00

标签: jsf-2 composite-component renderer

我想知道如何通过Java渲染复合组件, 我是说我有:

<myowntags:selectOneRadio>
  <f:selectItem itemValue="value0" itemLabel="This is the value 0" />
  <f:selectItem itemValue="value1" itemLabel="This is the value 1" />
  <f:selectItem itemValue="value2" itemLabel="This is the value 2" />
</myowntags:selectOneRadio>

<myowntags:selectOneRadio>
  <f:selectItems  value="#{controller.items}"  />
</myowntags:selectOneRadio>

我想创建一个Java类来渲染它。

我知道如何在不使用复合的情况下渲染自定义组件,但是因为要渲染组件,我必须在块上指定一些值:

<renderer>
    <component-family>javax.faces.SelectBoolean</component-family>
    <renderer-type>javax.faces.Checkbox</renderer-type>
    <renderer-class>com.myapp.CustomCheckboxRenderer</renderer-class>
</renderer>

然后我迷路了,因为我不知道那些参数的值 在复合组件的render标签内。

提前致谢, 天使。

1 个答案:

答案 0 :(得分:12)

首先,您需要一个支持组件来实现NamingContainer并返回"javax.faces.NamingContainer"作为组件系列。这是复合组件所必需的,您无法更改该组件。 UINamingContainer实现已经这样做了,所以如果你可以从中扩展它。

@FacesComponent("mySelectOneRadio")
public class MySelectOneRadio extends UINamingContainer {
    // ...
}

或者如果您想要从UISelectOne扩展,那么您必须实现NamingContainer界面,并确保在getFamily()覆盖中返回UINamingContainer.COMPONENT_FAMILY

然后,您需要在<cc:interface componentType>中指定它。

<cc:interface componentType="mySelectOneRadio">

请注意,在此步骤中,您已经可以通过Java执行呈现(编码)。只需覆盖encodeChildren()方法。

@FacesComponent("mySelectOneRadio")
public class MySelectOneRadio extends UINamingContainer {

    @Override
    public void encodeChildren(FacesContext context) throws IOException {
        ResponseWriter writer = context.getResponseWriter();
        writer.startElement("div", this);
        writer.writeText("hello world", null);
        writer.endElement("div");
    }

}

回到你的具体问题,你希望有一个独立的Renderer类。没关系。为此,您需要扩展Renderer

@FacesRenderer(componentFamily=UINamingContainer.COMPONENT_FAMILY, rendererType=MySelectOneRadioRenderer.RENDERER_TYPE)
public class MySelectOneRadioRenderer extends Renderer {

    public static final String RENDERER_TYPE = "com.example.MySelectOneRadio";

    @Override
    public void encodeChildren(FacesContext context, UIComponent component) throws IOException {
        ResponseWriter writer = context.getResponseWriter();
        writer.startElement("div", component);
        writer.writeText("hello world", null);
        writer.endElement("div");
    }

}

应该按如下方式更改支持组件,以便将此渲染器正确注册为默认渲染器(不要覆盖getRendererType()方法!否则您或其他任何人将无法通过{{1}更改此设置在<renderer>):

faces-config.xml

请注意,感谢@FacesComponent("myComposite") public class MyComposite extends UINamingContainer { public MyComposite() { // Set default renderer. setRendererType(MySelectOneRadioRenderer.RENDERER_TYPE); } } ,您无需为@FacesRenderer而烦恼。


无论您选择哪种方式对孩子进行编码,您都可以通过faces-config.xml获得组件的子项。当你在UIComponent#getChildren()组件内时:

MySelectOneRadio

或者当你在if (getChildCount() > 0) { for (UICompnent child : getChildren()) { // ... } } 渲染器内时:

MySelectOneRadioRenderer

要委派组件自己的默认呈现,请调用if (component.getChildCount() > 0) { for (UICompnent child : component.getChildren()) { // ... } } super.encodeChildren()。要委托子级自己的默认呈现,请调用component.encodeChildren()

另见: