Questions tagged [composite-component]

"Composite Component" is a JSF 2.x / Facelets specific term for reuseable UI components which are declared using pure XML rather than Java. The composite component XML declaration tags are available under the namespace `http://xmlns.jcp.org/jsf/composite`.

“Composite Component” is a JSF 2.x / Facelets specific term for reuseable UI components which are declared using pure XML rather than Java. The composite component XML declaration tags are available under the namespace http://xmlns.jcp.org/jsf/composite. Before JSF 2.2, the namespace http://java.sun.com/jsf/composite should be used instead.

Creating composite components

Prepare directory structure

First create a directory resources in the public webcontent (there where the WEB-INF directory and all regular Facelets files also are).

WebContent
 |-- WEB-INF
 |    `-- lib
 |-- resources   <---
 `-- test.xhtml

JSF 2.2 and later allows to change the resources directory by specifying a parameter named javax.faces.WEBAPP_RESOURCES_DIRECTORY in the file. It may be reasonable to change the directory to, for example, /WEB-INF/resources, since files under /WEB-INF are not readable via HTTP.

In the resources directory, create a directory exclusively for composite components. The directory name ends up as the extra path in the composite component namespace URI. You're free to choose the name. We'll take mycomponents as an example.

WebContent
 |-- WEB-INF
 |    `-- lib
 |-- resources
 |    `-- mycomponents   <---
 `-- test.xhtml

This way the composite components in this directory are available in all templates by the following namespace:

<html xmlns:my="http://xmlns.jcp.org/jsf/composite/mycomponents">

The prefix my is free to your choice. The http://xmlns.jcp.org/jsf/composite/ part is mandatory. The mycomponents part should be just the same as the directory name.

As a Hello World composite component example, we'll create composite component which shows a simple rating score with stars. We need to create a new XHTML file. The filename becomes the composite component tag name. You're free to choose the name. Let's call it rating.xhtml.

WebContent
 |-- WEB-INF
 |    `-- lib
 |-- resources
 |    `-- mycomponents
 |         `-- rating.xhtml   <---
 `-- test.xhtml

This way the composite component is available in all templates as follows:

<my:rating />

Create composite component

Here's how a basic composite component template look like. Put this in rating.xhtml.

<ui:component
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://xmlns.jcp.org/jsf/core"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
    xmlns:cc="http://xmlns.jcp.org/jsf/composite"
>
    <cc:interface>
        <!-- Define component attributes here -->
    </cc:interface>
    <cc:implementation>
        <!-- Define component body here -->
    </cc:implementation>
</ui:component>

We'd like to define the following attributes:

  • score, integer, required. The star score.
  • maxScore, integer, optional, default 100. The maximum possible score.
  • totalStars, integer, optional, default 10. The total amount of stars to display.

Now, here's how the final implementation look like. Note that the attributes are available by #{cc.attrs.attributename}.

<ui:component 
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://xmlns.jcp.org/jsf/core"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:cc="http://xmlns.jcp.org/jsf/composite"
    xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
    xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
    xmlns:fn="http://xmlns.jcp.org/jsp/jstl/functions"
>
    <cc:interface>
        <cc:attribute name="score" type="java.lang.Integer" required="true" />
        <cc:attribute name="maxScore" type="java.lang.Integer" default="100" />
        <cc:attribute name="totalStars" type="java.lang.Integer" default="10" />
    </cc:interface>
    <cc:implementation>
        <c:set var="filled" value="#{fn:substringBefore(cc.attrs.score / (cc.attrs.maxScore / cc.attrs.totalStars), '.')}" />
        <span style="font-size: 1.5em;">
            <c:forEach begin="1" end="#{cc.attrs.totalStars}" varStatus="loop">
                <h:outputText value="&#9733;" rendered="#{loop.index le filled}" />            
                <h:outputText value="&#9734;" rendered="#{loop.index gt filled}" />            
            </c:forEach>
        </span> 
    </cc:implementation>
</ui:component>

Here's how you can use it in test.xhtml:

<!DOCTYPE html>
<html lang="en"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://xmlns.jcp.org/jsf/core"
    xmlns:h="http://xmlns.jcp.org/jsf/html" 
    xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
    xmlns:my="http://xmlns.jcp.org/jsf/composite/mycomponents"
>
    <h:head>
        <title>Rating composite component demo</title>
    </h:head>
    <h:body>
        <my:rating score="60" /><br />
        <my:rating score="5" maxScore="10" /><br />
        <my:rating score="80" totalStars="5" /><br />
    </h:body>
</html>

Here's how the result should look like (only if your browser supports the Unicode star fonts; you're free to replace them by real images or even introduce a half star, which unfortunately isn't available in Unicode):

★★★★★★☆☆☆☆

★★★★★☆☆☆☆☆

★★★★☆

Create backing component

The above implementation has one disadvantage due to use the use of JSTL <c:forEach> : as JSTL runs during view build time instead of view render time, the above implementation cannot be used inside a repeating component such as <h:dataTable> or <ui:repeat>. We would like to use an <ui:repeat> instead, but it doesn't support begin and end attributes. So we'd like to attach some Java code so that it converts the totalStars to a blank object array of exactly that size so that it can be used in the value attribute. Ideally, this would be done using an EL function, but for learning/wiki purposes we'll use a so-called "backing component" instead.

To create such a backing component, we need to create a class which extends UINamingContainer or at least implements NamingContainer and returns UINamingContainer.COMPONENT_FAMILY in the getFamily() method. Here's a basic template:

package com.example;

import javax.faces.component.FacesComponent;
import javax.faces.component.UINamingContainer;

@FacesComponent("myCompositeComponent")
public class MyCompositeComponent extends UINamingContainer {

    // ...

}

Note the value of the @FacesComponent attribute. It's the one which you should specify in the componentType attribute of the <cc:interface> tag:

<cc:interface componentType="myCompositeComponent">

This way an instance of the backing component will be used behind the #{cc} variable instead. This offers you the possibility to define getter and action methods like value="#{cc.items}", action="#{cc.doSomething}" and so on. All of the <cc:attribute> attribues are available in the backing component by the inherited UIComponent#getAttributes() method which provides easy access to the attributes.

For our rating composite component, the backing component implementation should look like this:

package com.example;

import javax.faces.component.FacesComponent;
import javax.faces.component.UINamingContainer;

@FacesComponent("ratingComponent")
public class RatingComponent extends UINamingContainer {

    public Object[] getItems() {
        Object totalStars = getAttributes().get("totalStars");
        int size = Integer.valueOf(String.valueOf(totalStars));
        return new Object[size];
    }

}

And here's how the rating.xhtml should now look like:

<ui:component 
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://xmlns.jcp.org/jsf/core"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:cc="http://xmlns.jcp.org/jsf/composite"
    xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
    xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
    xmlns:fn="http://xmlns.jcp.org/jsp/jstl/functions"
>
    <cc:interface componentType="ratingComponent">
        <cc:attribute name="score" type="java.lang.Integer" required="true" />
        <cc:attribute name="maxScore" type="java.lang.Integer" default="100" />
        <cc:attribute name="totalStars" type="java.lang.Integer" default="10" />
    </cc:interface>
    <cc:implementation>
        <c:set var="filled" value="#{fn:substringBefore(cc.attrs.score / (cc.attrs.maxScore / cc.attrs.totalStars), '.')}" />
        <span style="font-size: 1.5em;">
            <ui:repeat value="#{cc.items}" varStatus="loop">
                <h:outputText value="&#9733;" rendered="#{loop.index lt filled}" />            
                <h:outputText value="&#9734;" rendered="#{loop.index ge filled}" />            
            </ui:repeat>
        </span>
    </cc:implementation>
</ui:component>

Note the value="#{cc.items}" in the above example. It basically calls getItems() method on the instance of the backing component. Also note that we got rid of JSTL <c:forEach>, so the above will work properly inside a repeating JSF component such as <ui:repeat>, <h:dataTable> and so on.

<h:dataTable value="#{bean.products}" var="product">
    <h:column>#{product.name}</h:column>
    <h:column><my:rating score="#{product.rating}" /></h:column>
</h:dataTable>

Online resources:

Related tag info pages:

775 questions
0
votes
1 answer

Get list with cc.attrs and ValueExpression on CompositeComponent JSF

I should create a composite component and insert it in a parent component. I tried to find the answer to my problem on stackOverflow and i found this: Add programmatically composite component in backing bean So, I create the composite component: …
Claudio Badii
  • 53
  • 1
  • 8
0
votes
1 answer

Problems using Composite JSF with DataTable

Well, i'm starting to use Composite JSF 2.0 and i have a following problem. This is my composite:
Mr.Lanhellas
  • 235
  • 2
  • 7
  • 16
0
votes
1 answer

jsf composite component nested EL

hi i want to pass a bean as parameter composite component, then i will call its function as an action.
acpuma
  • 479
  • 5
  • 15
0
votes
0 answers

JavaScript composite component nested forms

I have a simple composite component, which is nested in some form etc. I would like to bind the click event for all radio buttons in the of this composite component. I am trying to bind this event by name property of inputs which…
user2771738
  • 913
  • 11
  • 31
0
votes
1 answer

IPOJO - The factory associated with the component type is invalid (not started or missing handlers)

I am trying to learn how to use Felix iPOJO API to create components dynamically. I have a simple bundle with the following files: 1- HelloService.java (Contains a Service Interface). /* * @author zaid almahmoud * */ package…
Traveling Salesman
  • 2,209
  • 11
  • 46
  • 83
0
votes
1 answer

JSF2 Composite Component in Grails?

Is it possible to create reusable composite components (in JSF wording) in Grails? For the ones who do not know composites, here is the external link to JEE6 doc.
mert inan
  • 1,537
  • 2
  • 15
  • 26
0
votes
1 answer

Dynamic Reconfiguration in OW2 FraSCAti (Programmatically)

I am interested in the dynamic reconfiguration capabilities of OW2 FraSCAti. (e.g Starting/Stopping of SCA Components). So far, I can see that there are two ways to achieve this. 1- By using FraSCAti FScript, as the following: FraSCAtiFScript>…
0
votes
0 answers

jsf composite component with h:link outcome navigation could not be matched

I want to rewrite part of the code using composite component. I need to instead this:
0
votes
1 answer

Create customizable components

I am new to JSF. We are building a web application using JSF with primefaces. We have lot of places where we need to display table. The table should have paging, column resizeable, in some places we need context menu on right click, etc. I am able…
Lolly
  • 34,250
  • 42
  • 115
  • 150
0
votes
1 answer

How to nest a sub TabMenu inside a Primefaces TabMenu using composite components of JSF 2.0

I have two Primefaces TabMenus which I want to nest. There is an outer TabMenu with 3 tabs. the innerTabMenu is part of Tab 1 from the Outer TabMenu. I am using templates for each tab xhtml file. In the template I insert the composite…
novice22
  • 1
  • 3
0
votes
1 answer

NETBEANS 7.4: "no tag was defined for name: register" + “No library found for namespace http://java.sun.com/jsf/composite/my_composite_component”

I'm using Netbeans 7.4 on Linux Mint 13 Maya. I learn how to write a simple JSF composite component. But I have some errors: when I try to launch my app: Tag Library supports namespace:…
yak
  • 3,770
  • 19
  • 60
  • 111
0
votes
1 answer

PrimeFaces inputText not rendering sometimes

I'm here because I'm stuck with a very strange problem in my application which is the following : I have an e-commerce application with JSF and EJB, and I'm trying to fill out a form with user's informations. The problem is that my form is not…
Ko2r
  • 1,541
  • 1
  • 11
  • 24
0
votes
2 answers

How to do conditional update on a component

I have a JSF composite component which renders only some parts based on the attribute cc.attrs.list passed to it. In one of the components I want to update a set of other components based on the attribute. So something like this:
NeplatnyUdaj
  • 6,052
  • 6
  • 43
  • 76
0
votes
1 answer

How to use composite component

I'm create mycomponent.xhtml in the root of Web Pages directory. In mycomponent.xhtml i describe some composite component
user2953119
0
votes
1 answer

Using id-attribute in JSF 2 composite component with targets

I am trying to create a JSF 2.1 composite component for a button:
Gandalf
  • 2,350
  • 20
  • 28