Describes the Facelets2 tag library used for declaring and defining the usage contract for composite UI Components. When authoring a composite component, use of this tag library is largely optional, though always recommended. Declaring and defining a composite component with this taglib provides valuable information about the component that can be used by tools and users of the composite component. In most cases, a composite component can be authored without declaring and defining its usage contract with this taglib. PENDING: the limit of what one can do without declaring and defining a usage contract must be cleary specified and documented. PENDING: The implementation team must help discover these limits.
Creating a Composite Component
The default implementation must support authoring A composite component is declared by creating a Facelets2 file inside of a resource library. (See section 2.6 of the specification prose document for more information about resource libraries.) A composite component must reside within a resource library. It is not possible to create a composite component without putting it inside of a resource library.
The default XML namespace URI of the taglib that contains the composite component, for use in the using page, is http://java.sun.com/jsf/composite/<composite-library-name>
, where <composite-library-name>
is the name of the resource library. For example:
<!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:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:ez="http://java.sun.com/jsf/composite/ezcomp">
...
This declares that any Facelets2 file in the resource library called ezcomp
can be used as a regular JSF UI component in a page with the above namespace declaration by using the "ez
" prefix. For example, placing a file called foo.xhtml
in a resource library called ezcomp
would make that file accessible like this.
<ez:foo />
The implementation must also support declaring the namespace of the tag library in a JSF PDL tag library descriptor. This descriptor file is optional and is useful for component vendors that do not want to use the default XML namespace. This version of the proposal currently uses the facelet taglib descriptor syntax. For example:
<facelet-taglib>
<namespace>http://domain.com/path</namespace>
<composite-library-name>compositeTest</composite-library-name>
</facelet-taglib>
Components from that taglibrary may be used in a using page by declaring them in the XML namespace for that page:
<!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:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:ez="http://domain.com/path/namespace">
...
Below is an example of a fairly involved composite component declaration. Such a declaration might appear in foo.xhtml
.
displayName="Very Simple Login Panel"
preferred="true"
expert="false"
shortDescription="An illustration of the composite component feature">
<composite:attribute name="loginAction" required="true" method-signature="java.lang.Object action()"/ >
</composite:attribute>
<composite:attribute name="valueChangeListener" targets="username" />
<composite:attribute name="specialMethodExpression"
method-signature="com.foo.User validateCurrentUser()" />
<composite:attribute name="loginButtonLabel" default="Login" />
<composite:actionSource name="loginEvent" />
<composite:actionSource name="cancelEvent" />
<composite:actionSource name="allEvents" targets="loginEvent,cancelEvent" />
</composite:interface>
<ui:decorate template="fooTemplate.xhtml">
<ui:define name="header">
<p>This is the login panel header</p>
</ui:define>
<ui:define name="body">
<p>
<h:inputText id="username" />
</p>
<p>
<h:commandButton id="loginEvent"
value="#{compositeComponent.attrs.loginButtonLabel}">
</h:commandButton>
<h:commandButton id="cancelEvent" value="Cancel" action="cancel">
</h:commandButton>
<special:validateUserButton
validateUser="#{compositeComponent.attrs.specialMethodExpression}" />
</p>
</ui:define>
<ui:define name="footer">
<p>This is the login panel footer</p>
</ui:define>
</ui:decorate>
</composite:implementation>
The values for attributes in a composite component PDL file can be fully localized by putting them inside a ResourceBundle in the same directory as the PDL page and accessing them with the per-component resource bundle syntax. Consider the file foo.xhtml
, in the resource library ezcomp
. The shortDescription
element could be changed to be:
<composite:interface shortDescription="#{compositeComponent.resourceBundleMap.shortDescription}" >
In this case, In the same ezcomp
directory as foo.xhtml
, there would be a foo.properties
file that would contain this entry:
shortDescription=A really nifty login panel.
The normal localization rules for ResourceBundle
would apply.
Tag Summary |
interface | This element declares the usage contract for a composite component. Optionally, and at the component author's discretion, this contract exposes the features of one or more inner components to the page author. The page author can work with the composite component as a single component whose feature set is the union of the features declared in the usage contract. For example, consider a composite component that implements the functionality of a "login panel". Such a component would likely have two text fields and one button. The user of such a component might like to do one or more of the following. Be able to listen for the ActionEvent on the button. In this case, a <composite:actionSource> element is included in the usage contract that refers to the inner button in the <composite:implementation> section. Provide an "action" to invoke when the button is pressed. In this case, a <composite:attribute> element is included in the usage contract that refers to the inner button in the <composite:implementation> section and declares the proper method signature for an "action". Provide parameters to the composite component for labels and other rendering specific aspects of the composite component. In this case, one or more <composite:attribute> elements are included in the usage contract and those parameters are referred to in the <composite:implementation> section using EL expressions like #{compositeComponent.attrs.usernameLabel} , assuming usernameLabel is the name of one of the <composite:attribute> elements in the usage contract. Add ValueChangeListener s, Converter s, or Validator s to either or both text fields. In this case, a <composite:editableValueHolder> element is included in the usage contract that refers to the inner text field in the <composite:implementation> section. In the case of wanting to enable only adding a Converter (and not a ValueChangeListener or Validator , a <composite:valueHolder> element would be used. Add facet children to the login panel. In this case, a <composite:facet> element is included in the usage contract that refers to the inner <composite:insertFacet> element in the <composite:implementation> section. For each of the behaviorial interfaces in Section 3.2 of the specification, there is a tag in the composite: library to nest inside of the <composite:interface> section. If the <composite:interface> section is not present in a PDL page, the contract will be inferred as described in the specification. There must be zero or one of these elements in a composite component PDL file. If a <composite:interface> element does appear, there must be an accompanying <composite:implementation> element in the same PDL file. |
implementation | Defines the implementation of the composite component. There must be zero or one of these in a composite component markup file. If a <composite:interface> element appears, there must be a corresponding <composite-implementation> element. If no <composite:interface> element appears, the <composite-implementation> element is optional. |
attribute | Declares an attribute that may be given to an instance of the composite component tag for this composite component. There may be zero or many of these inside of the <composite:interface > section. This element may be nested within other <composite:attribute> elements to convey a usage contract that includes nested properties. Please see summary page for a usage example. |
facet | Declares that this composite component supports a facet with the name given by the value of the "name" attribute. Please see <composite:interface> for a usage example. |
insertFacet | This element is used in the <composite:implementation> section. The facet with the name equal to the value of the name attribute, given by the page author in the using page, will be rendered at this point in the composite component PDL page. The implementation of this tag handler must insert a component with component-type javax.faces.Output and renderer-type javax.faces.ConsumingPageCompositeChildren as a child at this point in the component tree. The implementation of this tag handler must store an attribute into the created component's attribute map under the key given by the value of the symbolic constant UIComponent.FACETS_KEY . The value for this key must be the evaluated value of the "name" attribute. |
insertChildren | This element is used in the <composite:implementation> section. Any child components or template text within the composite component tag in the using page will be inserted into the rendered output at this point in the composite component PDL page. The implementation of this tag handler must insert a component with component-type javax.faces.Output and renderer-type javax.faces.ConsumingPageCompositeChildren as a child at this point in the component tree. |
valueHolder | Declares that the composite component whose contract is declared by the <composite:interface> in which this element is nested exposes an implementation of ValueHolder suitable for use as the target of attached objects in the using page. Any attached objects suitable for implementations of ValueHolder may be attached to the composite component. Consider this excerpt from the using page: <ez:foo> <f:converter for="userid" binding="#{bean.converter}" /> </ez:foo>
Line 2 refers to the <composite:valueHolder> declaration on line 2 of foo.xhtml : <composite:interface> <composite:valueHolder name="userid" /> </composite:interface> <composite:implementation> <h:inputText id="userid" /> </composite:implementation>
It is possible to declare that a single <composite:valueHolder> element should cause multiple components within the <composite:implementation> section to be the targets of an attached object in the using page. Assuming the same using page excerpt as above, the revised PDL page is: <composite:interface> <composite:valueHolder targets="userid,password" /> </composite:interface> <composite:implementation> <h:inputText id="userid" /> <h:inputText id="password" /> </composite:implementation>
In this case, the "targets" attribute on the <composite:valueHolder> element, on line 2 above, replaces the "name" attribute in the previous example. "targets" is a list of ids of components within the <composite:implementation> section. In this case, "targets" refers to the <h:inputText> components on lines 6 and 7 above. Please see <composite:interface> for a usage example. |
editableValueHolder | Declares that the composite component whose contract is declared by the <composite:interface> in which this element is nested exposes an implementation of EditableValueHolder suitable for use as the target of attached objects in the using page. Any attached objects suitable for implementations of EditableValueHolder may be attached to the composite component.The example from <composite:valueHolder> still applies. Please see <composite:interface> for a usage example. |
actionSource | Declares that the composite component whose contract is declared by the <composite:interface> in which this element is nested exposes an implementation of ActionSource2 suitable for use as the target of attached objects in the using page. Any attached objects suitable for implementations of ActionSource2 may be attached to the composite component. Consider this excerpt from the using page: <ez:loginPanel id="loginPanel" model="#{bean}"> <f:valueChangeListener for="username" binding="#{bean.useridValueChangeListener}" /> <f:actionListener for="loginEvent" binding="#{bean.loginEventListener}" /> <f:actionListener for="cancelEvent" binding="#{bean.cancelEventListener}" /> <f:actionListener for="allEvents" binding="#{bean.allEventsListener}" /> </ez:loginPanel>
The <f:actionListener> elements on lines 4, 7, and 10 refer to the attached objects declared on lines 2, 3 and 4 below. <composite:interface name="loginPanel"> <composite:actionSource name="loginEvent" /> <composite:actionSource name="cancelEvent" /> <composite:actionSource name="allEvents" targets="loginEvent,cancelEvent" /> </composite:interface>
Most of the concepts from example content from <composite:valueHolder> also applies in the case of <composite:actionSource> . Please see <composite:interface> for a usage example. |