如何使用自定义渲染器渲染复合组件? [英] How to render a composite component using a custom renderer?

查看:128
本文介绍了如何使用自定义渲染器渲染复合组件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道如何通过Java渲染复合组件, 我的意思是:

I would like to know how to render a composite component, through Java, I mean I have:

<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类来呈现它.

and I would like to create a Java class to render it.

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

I know how to render a custom component without using composite, but since, to render a component I have to specify some values on the block:

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

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

then I get lost, because I don't know the values of those parameters inside the render tag for a composite component.

预先感谢, 天使.

推荐答案

首先,您需要具有一个实现作为组件族.复合组件需要这样做,您不能更改该零件. UINamingContainer 实现已经做到了,所以如果您可以从中扩展的话.

First, you need to have a backing component which implements NamingContainer and returns "javax.faces.NamingContainer" as component family. This is required by composite components, you can't change that part. The UINamingContainer implementation already does that, so if you can just extend from it.

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

或者,如果您想从UISelectOne扩展,则必须实现NamingContainer接口,并确保返回

Or if you rather want to extend from UISelectOne, then you'd have to implement the NamingContainer interface and make sure that you return UINamingContainer.COMPONENT_FAMILY in the getFamily() override.

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

Then, you need to specify it in <cc:interface componentType>.

<cc:interface componentType="mySelectOneRadio">


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


Note that at this step you can already perform the rendering (encoding) through Java. Just override the encodeChildren() method.

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


Coming back to your concrete question, you'd thus like to have a standalone Renderer class for this. That's fine. For that you need to extend 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()方法!否则您或其他任何人将无法通过faces-config.xml中的<renderer>进行更改) >):

The backing component should be changed as follows in order to properly register this renderer as the default renderer (don't override getRendererType() method! otherwise you or anyone else would be unable to change this by <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所困扰.

Note that thanks to the @FacesRenderer, you don't need to hassle with faces-config.xml.

无论选择哪种方式编码子代,都可以通过UIComponent#getChildren()来获取组件的子代.当您进入MySelectOneRadio组件时:

Whatever way you choose to encode the children, you can get component's children just by UIComponent#getChildren(). When you're inside MySelectOneRadio component:

if (getChildCount() > 0) {
    for (UICompnent child : getChildren()) {
        // ...
    }
}

或者在MySelectOneRadioRenderer渲染器中时:

if (component.getChildCount() > 0) {
    for (UICompnent child : component.getChildren()) {
        // ...
    }
}

要委派给组件自己的默认呈现,请调用super.encodeChildren()component.encodeChildren().若要委派给孩子自己的默认渲染,请调用child.encodeAll().

To delegate to the component's own default rendering, invoke super.encodeChildren() or component.encodeChildren(). To delegate to child's own default rendering, invoke child.encodeAll().

这篇关于如何使用自定义渲染器渲染复合组件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆