代码之家  ›  专栏  ›  技术社区  ›  drodil

以编程方式在backingbean中创建和添加复合组件

  •  8
  • drodil  · 技术社区  · 12 年前

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

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

    但在列内部什么都没有呈现。有什么想法可以做到吗?我不想使用rendered=“#{bean.isThisRendered}”的方式,因为它不适合我的用例。

    1 回复  |  直到 12 年前
        1
  •  11
  •   BalusC    12 年前

    此代码不完整。你需要使用 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");