如何为数据表列创建复合组件?
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 标签本身。这种折衷是有效的,因为<my:mycolumn>
元素必须是 UIColumn
的一个实例,因为这是在呈现响应阶段UIData
组件的唯一有效子级。所有其他 UIComponent
类型将被忽略,因此不会呈现。复合组件隐含地是 UINamingContaner
组件,它不是 UIColumn
,因此被忽略。
带有扩展 UIColumn
的支持组件的 PrimeFaces <p:dataTable>
也将由于复合组件的错误生命周期而无法工作。列必须在视图构建时创建,而复合组件的主体是在视图渲染时创建。
解决方案是创建一个标记文件,这意味着一个额外的.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>
注意:<attribute>
条目不是强制性的,但非常适合用于文档目的,例如生成的文档和 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。但是用这种方法你不能用一些<cc:insertChildren/>
来添加孩子,可以吗?有没有办法使用 jsf/composite
标签并说根 UIComponent 必须是 javax.faces.component.UIColumn
?
@Anthony:只需使用<ui:insert>
。不,复合材料没有办法,正如已经回答的那样。
这种变通方法似乎是 JSF 规范中的一个巨大疏忽。上述解决方案也适用于我;但是,我将如何模拟具有新定义的方面的 cc:renderFacet?带有名称的 Ui:define/ui:insert 对我有用。但是,有没有办法仍然提供另一个 f:facet 子并在 column.xhtml 中使用一些等效的 cc:renderFacet?
这一切都很好,但是,为什么我需要编写一个“my.tablib.xml”并在 web.xml 中声明它,而这种机制不需要定义复合材料?
@MartinHöller 在column.xhtml
的定义中,您可以使用<ui:insert />
来定义放置子标签的位置。看来您也可以像使用模板一样定义命名插入点。我测试了将<ui:insert name="foo" />
添加到column.xhtml
中,并使用<my:column><ui:define name="foo">hello quasi facet</ui:define></my:column>
从外部引用它——这似乎有效,即使与直接孩子的未命名<ui:insert />
结合使用。以上是关于如何为数据表列创建复合组件?的主要内容,如果未能解决你的问题,请参考以下文章