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>

複合コンポーネントのrenderタグ内のこれらのパラメーターの値がわからないため、迷子になります。

よろしくお願いします、エンジェル。

4

1 に答える 1

15

まず、コンポーネントファミリとして実装NamingContainerして返すバッキングコンポーネントが必要です。"javax.faces.NamingContainer"これは複合コンポーネントに必要であり、その部分を変更することはできません。実装はすでにそれUINamingContainerを行っているので、それから拡張できるのであれば。

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

または、から拡張したい場合は、インターフェイスUISelectOneを実装し、オーバーライドで戻るようにする必要があります。NamingContainerUINamingContainer.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");
    }

}

このレンダラーをデフォルトのレンダラーとして適切に登録するには、バッキングコンポーネントを次のように変更する必要があります(メソッドをオーバーライドしないでください。そうしないと、あなたや他の人がinでgetRendererType()これを変更できなくなります)。<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()。子自身のデフォルトレンダリングに委任するには、を呼び出しchild.encodeAll()ます。

参照:

于 2012-09-21T13:10:49.560 に答える