Dynamic 以编程方式在支持bean中创建和添加复合组件

Dynamic 以编程方式在支持bean中创建和添加复合组件,dynamic,jsf-2,facelets,composite-component,Dynamic,Jsf 2,Facelets,Composite Component,我正在使用一个动态仪表板,用户可以根据自己的喜好锁定和删除项目。现在我有一个问题,我想将现有的复合组件从支持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

我正在使用一个动态仪表板,用户可以根据自己的喜好锁定和删除项目。现在我有一个问题,我想将现有的复合组件从支持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>
下面是我如何使用该函数的:

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

但在列内部没有渲染任何内容。你知道怎么做吗?我不想使用rendered=“#{bean.isThisRendered}”方式,因为它不适合我的用例。

此代码不完整。您需要在复合组件实现中包含复合组件资源。这里有一个实用的方法来完成这项工作。有父对象在手是很重要的,因为它是在EL范围内创建
{cc}
的上下文。因此,此实用程序方法也会立即将该组合添加为给定父对象的子对象。此外,为复合组件提供一个固定的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);
    }
}

非常有趣!是否可以使用此方法(可能稍作修改)包含外部组件?我希望包括应用程序中未定义的组件,而不是使用现有资源。@fnst:如果需要,可以使用自定义资源处理程序控制资源处理。只要您最终得到一个有效的
URL
,它基本上可以指向所有内容(包括
文件://
http://
,甚至自定义协议,以便理论上可以访问数据库)。感谢您的回答,必须尝试:)也可以添加值表达式作为复合组件的属性吗?不客气。我不知道你具体在问什么。这是你的赏金:)无论如何,我已经回答了我自己的问题。。例如,使用时为复合组件添加值表达式的代码可以通过新函数参数Map valueExpressions和ExpressionFactory=application.getExpressionFactory()实现;ELContext ctx=context.getELContext();for(Map.Entry-Entry:valueExpressions.entrySet()){ValueExpression-expr=factory.createValueExpression(ctx,Entry.getValue(),String.class);composite.setValueExpression(Entry.getKey(),expr);}出于兴趣(该主题涉及面太广,这会让我提前几光年):在哪里调用3行调用
HtmlUtil.getCompositeComponent
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");