以编程方式在支持 bean 中创建和添加复合组件 [英] Programmatically create and add composite component in backing bean

查看:21
本文介绍了以编程方式在支持 bean 中创建和添加复合组件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用一个动态仪表板,用户可以在其中根据需要固定和删除项目.现在我有一个问题,我想将现有的复合组件从支持 bean 添加到视图.我试图从互联网上找到正确的方法来做到这一点,但到目前为止没有成功.这是我要添加的简单复合组件:

I am working with a dynamic dashboard where users can pin and remove items as they like. Now I have a problem that I want to add existing composite component to the view from the backing bean. I've tried to find correct way to do this from the internet but no success so far. Here is the simple composite component I want to add:

<?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>

这是应该返回复合组件的代码:

Here is the code which should return the composite component:

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;
}

这是我使用该功能的方式:

And here is how I am using the function:

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

但是列内没有渲染任何内容.任何想法如何做到这一点?我不想使用 render="#{bean.isThisRendered}" 方式,因为它不适合我的用例.

But nothing is rendered inside the column. Any ideas how this could be done? I don't want to go with the rendered="#{bean.isThisRendered}" way because it does not fit in my use case.

推荐答案

此代码不完整.您需要使用 FaceletContext#includeFacelet() 之后在复合组件实现中包含复合组件资源.这是完成这项工作的实用方法.掌握父级很重要,因为它是 #{cc} 应该在 EL 作用域中创建的上下文.因此,此实用程序方法还会立即将组合添加为给定父级的子级.此外,给复合组件一个固定的 ID 很重要,否则 JSF 将无法处理复合内部的任何表单/输入/命令组件.

This code is incomplete. You need to use FaceletContext#includeFacelet() afterwards to include the composite component resource in the composite component implementation. Here's an utility method which does the job. It's important to have the parent at hands, as it is the context where the #{cc} should be created in the EL scope. So this utility method also immediately adds the composite as a child of the given parent. Further, it's important to give the composite component a fixed ID, otherwise JSF wouldn't be able to process any form/input/command components inside the composite.

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);
    }
}

因此,在您的特定示例中,请按如下方式使用它:

So, in your particular example, use it as follows:

includeCompositeComponent(column, "comp", "test.xhtml", "someUniqueId");

这篇关于以编程方式在支持 bean 中创建和添加复合组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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