如何为数据表列创建复合组件?

Posted

技术标签:

【中文标题】如何为数据表列创建复合组件?【英文标题】:How to create a composite component for a datatable column? 【发布时间】:2012-07-11 11:57:06 【问题描述】:

鉴于这个数据表(自然工作):

<rich:dataTable var="var" value="#values">
<rich:column>
  <f:facet name="header">
   HEADER
  </f:facet>
  <h:outputText value="#var" />
</rich:column>
</rich:dataTable>

如果我定义了一个自定义组件(在语法和资源/组件下的正确位置也可以):

   <?xml version="1.0" encoding="UTF-8"?>
    <html xmlns="http://www.w3.org/1999/xhtml"
        xmlns:ui="http://java.sun.com/jsf/facelets"
        xmlns:f="http://java.sun.com/jsf/core"
        xmlns:h="http://java.sun.com/jsf/html"
        xmlns:a4j="http://richfaces.org/a4j"
        xmlns:rich="http://richfaces.org/rich"
        xmlns:composite="http://java.sun.com/jsf/composite">

    <!-- INTERFACE -->
    <composite:interface>
        <composite:attribute name="val" />
    </composite:interface>

    <!-- IMPLEMENTATION -->
    <composite:implementation>
        <rich:column>
            <f:facet name="header">
       HEADER
       </f:facet>
       <h:outputText value="#cc.attrs.val" />
       </rich:column>
    </composite:implementation>
    </html>

为什么以下不起作用?

<?xml version="1.0" encoding="UTF-8"?>
<ui:composition template="/WEB-INF/templates/default.xhtml"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:a4j="http://richfaces.org/a4j"
    xmlns:rich="http://richfaces.org/rich"
    xmlns:my="http://java.sun.com/jsf/composite/components">
    <ui:define name="content">
        <rich:dataTable var="var" value="#values">
                 <my:mycolumn val="#var"/>
                </rich:dataTable>
    </ui:define>
</ui:composition>

你知道我怎样才能让它工作(我想定义我自己的列并保存代码)吗?非常感谢!再见

【问题讨论】:

【参考方案1】:

我遇到了同样的问题(primefaces),我的妥协:从复合中排除列标签

<rich:dataTable var="var" value="#values">
    <rich:column rendered=#yesOrNo">
       <my:mycolumn val="#var">
       .. with child nodes if you want ...
       </my:mycolumn>
    </rich:column>
</rich:dataTable>

【讨论】:

这是一个非常奇怪且不合逻辑的答案如果包含实际上不正确的代码。而且您没有排除列而是包含它,很奇怪。 OP 的组合包含rich:column 标签本身。这种折衷是有效的,因为 在复合之外(这就是为什么它可以在视图构建期间创建,而复合组件的主体是在视图渲染期间创建的,正如 BalusC 所说)如果复合包含大代码(就我而言),这可能会有所帮助。语法:它使用问题中的变量和结构。【参考方案2】:

&lt;my:mycolumn&gt; 元素必须是 UIColumn 的一个实例,因为这是在呈现响应阶段UIData 组件的唯一有效子级。所有其他 UIComponent 类型将被忽略,因此不会呈现。复合组件隐含地是 UINamingContaner 组件,它不是 UIColumn,因此被忽略。

带有扩展 UIColumn 的支持组件的 PrimeFaces &lt;p:dataTable&gt; 也将由于复合组件的错误生命周期而无法工作。列必须在视图构建时创建,而复合组件的主体是在视图渲染时创建。

解决方案是创建一个标记文件,这意味着一个额外的.taglib.xml 文件,但它可以完美运行。

/WEB-INF/tags/column.xhtml:

<ui:composition
    xmlns="http://www.w3.org/1999/xhtml" 
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets" 
    xmlns:rich="http://richfaces.org/rich">
    <rich:column>
        <f:facet name="header">HEADER</f:facet>
        <h:outputText value="#val" />
    </rich:column>
</ui:composition>

/WEB-INF/my.taglib.xml:

<?xml version="1.0" encoding="UTF-8"?>
<facelet-taglib 
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd"
    version="2.0">
    <namespace>http://example.com/my</namespace>
    <tag>
        <tag-name>column</tag-name>
        <source>tags/column.xhtml</source>
        <attribute>
            <description>Column value</description>
            <name>val</name>
        </attribute>
    </tag>
</facelet-taglib>

注意:&lt;attribute&gt; 条目不是强制性的,但非常适合用于文档目的,例如生成的文档和 IDE 自动完成。

/WEB-INF/web.xml:

<context-param>
    <param-name>javax.faces.FACELETS_LIBRARIES</param-name>
    <param-value>/WEB-INF/my.taglib.xml</param-value>
</context-param>

用法:

<ui:composition
    xmlns="http://www.w3.org/1999/xhtml" 
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets" 
    xmlns:rich="http://richfaces.org/rich"
    xmlns:my="http://example.com/my">
    <rich:dataTable value="#values" var="value">
        <my:column val="#value" />
    </rich:dataTable>
</ui:composition>

【讨论】:

非常感谢 BalusC。但是用这种方法你不能用一些&lt;cc:insertChildren/&gt; 来添加孩子,可以吗?有没有办法使用 jsf/composite 标签并说根 UIComponent 必须是 javax.faces.component.UIColumn @Anthony:只需使用&lt;ui:insert&gt;。不,复合材料没有办法,正如已经回答的那样。 这种变通方法似乎是 JSF 规范中的一个巨大疏忽。上述解决方案也适用于我;但是,我将如何模拟具有新定义的方面的 cc:renderFacet?带有名称的 Ui:define/ui:insert 对我有用。但是,有没有办法仍然提供另一个 f:facet 子并在 column.xhtml 中使用一些等效的 cc:renderFacet? 这一切都很好,但是,为什么我需要编写一个“my.tablib.xml”并在 web.xml 中声明它,而这种机制不需要定义复合材料? @MartinHöller 在column.xhtml 的定义中,您可以使用&lt;ui:insert /&gt; 来定义放置子标签的位置。看来您也可以像使用模板一样定义命名插入点。我测试了将&lt;ui:insert name="foo" /&gt; 添加到column.xhtml 中,并使用&lt;my:column&gt;&lt;ui:define name="foo"&gt;hello quasi facet&lt;/ui:define&gt;&lt;/my:column&gt; 从外部引用它——这似乎有效,即使与直接孩子的未命名&lt;ui:insert /&gt; 结合使用。

以上是关于如何为数据表列创建复合组件?的主要内容,如果未能解决你的问题,请参考以下文章

如何为数据框中的复杂列创建包含数组(案例类)的udf

我如何为固定数据表组件的单元格设置动画?

在sql创建数据库表时,如何为字段设一个默认值

Ebean:如何为没有属性的getter创建列

如何按数据范围查询 Cassandra 中以 TimeUUID 为第一个组件的复合列?

如何为列中的每个唯一值获取数据框中的项目数[重复]