4

我想知道如何通过 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>

然后我迷路了,因为我不知道复合组件的渲染标记内这些参数的值。

提前感谢,天使。

4

1 回答 1

15

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

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

或者,如果您想从 扩展UISelectOne,则必须实现NamingContainer接口并确保UINamingContainer.COMPONENT_FAMILYgetFamily()覆盖中返回。

然后,您需要在<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()方法!否则您或其他任何人将无法通过<renderer>in更改它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(). 要委托给孩子自己的默认渲染,请调用child.encodeAll().

也可以看看:

于 2012-09-21T13:10:49.560 回答