8

ユーザーが好きなようにアイテムを固定および削除できる動的ダッシュボードを使用しています。今、既存の複合コンポーネントをバッキング Bean からビューに追加したいという問題があります。インターネットからこれを行う正しい方法を見つけようとしましたが、これまでのところ成功していません。追加したい単純な複合コンポーネントは次のとおりです。

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:cc="http://java.sun.com/jsf/composite"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:p="http://primefaces.org/ui"
      xmlns:composite="http://java.sun.com/jsf/composite">
    <!-- INTERFACE -->
    <cc:interface>

    </cc:interface>

    <!-- IMPLEMENTATION -->
    <cc:implementation>
        <h:outputText value="TEST"/>
    </cc:implementation>
</html>

複合コンポーネントを返すコードは次のとおりです。

public static UIComponent getCompositeComponent(String xhtml, String namespace) {
    FacesContext fc = FacesContext.getCurrentInstance();
    Application app = fc.getApplication();
    Resource componentResource = app.getResourceHandler().createResource(xhtml, namespace);

    UIPanel facet = (UIPanel) app.createComponent(UIPanel.COMPONENT_TYPE);
    facet.setRendererType("javax.faces.Group");
    UIComponent composite = app.createComponent(fc, componentResource);
    composite.getFacets().put(UIComponent.COMPOSITE_FACET_NAME, facet);

    return composite;
}

そして、これが私が関数を使用している方法です:

Column column = new Column();
UIComponent test = HtmlUtil.getCompositeComponent("test.xhtml", "comp");
column.getChildren().add(test);

ただし、列内には何もレンダリングされません。これを行う方法はありますか?render="#{bean.isThisRendered}" の方法は使用したくありません。これは私のユース ケースに適合しないためです。

4

1 に答える 1

11

このコードは不完全です。FaceletContext#includeFacelet()後で使用して、複合コンポーネント リソースを複合コンポーネントの実装に含める必要があります。これは、仕事をするユーティリティメソッドです。#{cc}EL スコープで を作成する必要があるコンテキストであるため、親を手元に置くことが重要です。したがって、このユーティリティ メソッドは、コンポジットを指定された親の子としてすぐに追加します。さらに、複合コンポーネントに固定 ID を付与することが重要です。そうしないと、JSF は複合内のフォーム/入力/コマンド コンポーネントを処理できなくなります。

public static void includeCompositeComponent(UIComponent parent, String libraryName, String resourceName, String id) {
    // Prepare.
    FacesContext context = FacesContext.getCurrentInstance();
    Application application = context.getApplication();
    FaceletContext faceletContext = (FaceletContext) context.getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY);

    // This basically creates <ui:component> based on <composite:interface>.
    Resource resource = application.getResourceHandler().createResource(resourceName, libraryName);
    UIComponent composite = application.createComponent(context, resource);
    composite.setId(id); // Mandatory for the case composite is part of UIForm! Otherwise JSF can't find inputs.

    // This basically creates <composite:implementation>.
    UIComponent implementation = application.createComponent(UIPanel.COMPONENT_TYPE);
    implementation.setRendererType("javax.faces.Group");
    composite.getFacets().put(UIComponent.COMPOSITE_FACET_NAME, implementation);

    // Now include the composite component file in the given parent.
    parent.getChildren().add(composite);
    parent.pushComponentToEL(context, composite); // This makes #{cc} available.
    try {
        faceletContext.includeFacelet(implementation, resource.getURL());
    } catch (IOException e) {
        throw new FacesException(e);
    } finally {
        parent.popComponentFromEL(context);
    }
}

したがって、特定の例では、次のように使用します。

includeCompositeComponent(column, "comp", "test.xhtml", "someUniqueId");
于 2013-04-08T16:15:32.340 に答える