问题
Given this datatable (naturally working):
<rich:dataTable var=\"var\" value=\"#{values}\">
<rich:column>
<f:facet name=\"header\">
HEADER
</f:facet>
<h:outputText value=\"#{var}\" />
</rich:column>
</rich:dataTable>
If I define a custom component (also ok in the syntax and at the right place under resources/components):
<?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>
Why does the following does not work?
<?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>
Do you know how could I let it work (I want to define my own column and save code)? Thanks a lot! Bye
回答1:
The <my:mycolumn>
element must be an instance of UIColumn
as that's the only valid child of a UIData
component during the render response phase. All other UIComponent
types will be ignored, thus not rendered. A composite component is implicitly a UINamingContaner
component, which isn't a UIColumn
and therefore ignored.
A PrimeFaces <p:dataTable>
with a backing component that extends UIColumn
also won't work due to the wrong lifecycle of a composite component. The column has to be created during the view build time, while the composite component's body is created during view render time.
The solution is to create a tag file instead, which means an extra .taglib.xml
file, yet it works flawlessly.
/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>
Note: The <attribute>
entries are not mandatory, but are nice for documentation purposes, such as generated docs and IDE autocomplete.
/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>
Usage:
<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>
来源:https://stackoverflow.com/questions/11439886/how-to-create-a-composite-component-for-a-datatable-column