Component inside Composite referencing another component inside other component - jsf

I created a Composite Component to emulate the Primefaces's Column, which instead render to components, its renderize to (I also created other components to emulate Primefaces's PanelGrid and Row to use DIVs instead Table and TR). The code is the following:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui"
xmlns:cc="http://java.sun.com/jsf/composite">
<cc:interface>
<cc:attribute name="id" type="java.lang.String" required="false"/>
<cc:attribute name="span" type="java.lang.Integer" required="false" default="1" />
</cc:interface>
<cc:implementation>
<p:outputPanel id="#{cc.attrs.id}" layout="block"
styleClass="ui-grid-col-#{cc.attrs.span}">
<cc:insertChildren />
</p:outputPanel>
</cc:implementation>
</html>
My problem happens when I use a outputLabel referrecing a component to an outside's component:
<ipem:column span="2">
<p:outputLabel value="#{msg['precadastro.titulo.nome_fantasia']}" for="fantasia"/>
</ipem:column>
<ipem:column span="10">
<p:inputText id="fantasia" size="80" maxlength="100"
value="#{preCadastroMB.preCadastro.nomeFantasia}" />
</ipem:column>
When I wrote this, I got the message Cannot find component with identifier "fantasia" referenced from "painelCadastro:j_idt80:j_idt82:j_idt84". I need remove the for attribute in outputLabel.
I found some questions here in StackOverflow which are near my doubt. For example, in How to make a grid of JSF composite component? we have an outputLabel in the parent page which references a component inside a composite. However, in my case, both label as inputText are inside its own composite. In How to create a composite component for a datatable column? the label and inputText are both in the same composite.
We don't have this problem Column's Primefaces. How do they manage this?
Thanks,
Rafael Afonso

Related

Avoiding duplicate ids when reusing facelets compositions in the same naming container

I have a <ui:composition> that contains a few elements with explicit ids and some ajax events which reference these ids for partial processing/updating. I encapsulated this fragment of xhtml inside the composition simply so I could use it in a few different places without having to duplicate the code. However, when I use the composition (with <ui:include>) more than once inside a page, I get duplicate id exceptions. It seems JSF is not wrapping each composition inside its own naming container (like <ui:component> does).
Is there a simple way to wrap my composition inside its own naming container?
Or do I have to use a composite component every time I want to reuse xhtml fragments inside a common naming container?
Depending on the purpose of the <ui:include> template, you've several options:
Use <f:subview>. It creates another NamingContainer context (like as <h:form>, <h:dataTable>, and friends all do):
<f:subview id="top">
<ui:include src="/WEB-INF/includes/some.xhtml" />
</f:subview>
...
<f:subview id="bottom">
<ui:include src="/WEB-INF/includes/some.xhtml" />
</f:subview>
The components definied in some.xhtml will end up getting respectively top: and bottom: prefix in their ID.
Turn it into a tagfile which requires an id attribute.
<my:some id="top" />
...
<my:some id="bottom" />
And use that ID to prefix the ID of the components in the composition.
<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"
>
...
<h:someComponent id="#{id}_some" />
<h:otherComponent id="#{id}_other" />
...
<ui:composition>
Turn it into a composite component. Composite components are inherently already a NamingContainer, so their id attribute is optional. Basically, replace
<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"
>
...
<ui:composition>
by
<ui:component
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:cc="http://java.sun.com/jsf/composite"
>
<cc:interface>
<!-- This is optional. -->
</cc:interface>
<cc:implementation>
...
<h:someComponent id="some" />
<h:otherComponent id="other" />
...
</cc:implementation>
<ui:component>
This way you can use it as follows:
<my:some id="top" />
...
<my:some id="bottom" />
The components definied in <cc:implementation> will end up getting respectively top: and bottom: prefix in their ID (note again, the composite component's id attribute is optional, JSF will otherwise autogenerate one).
See also:
When to use <ui:include>, tag files, composite components and/or custom components?
When you include more than once the same ui:composition the id are duplicated. The solution is to specifiy a particular ui:param within the ui:include.
Assuming you're including mycomposition.xhtml you can do something similar:
<ui:include src="mycomposition.xhtml">
<ui:param name="idPrefix" value="first"/>
</ui:include>
...
<ui:include src="mycomposition.xhtml">
<ui:param name="idPrefix" value="second"/>
</ui:include>
Then in the mycomposition.xhtml you should declare the ids as follows (for instance a h:outputText):
<h:outputText id="#{idPrefix}_text" value="My Awesome Text here"/>
Now you can reference the id in the rest of yout page as #{idPrefix}_text.

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 to implement this with dataTable component provided by primefaces. But I would like to create it as more customizable component. Some thing like reusable javascript/jquery (Jqgrid) plugin where we just set few property values which should be should be enough.
I would also want to do the similar way instead of writing the whole code for all the functionality, if a component is created which can be reused in all places and set parameters (Eg: columnResizable='true', columnSortable='true') which saves development time.
I am not getting any picture of how to accomplish it. If some one can guide that will be great. I am not expecting entire code, any idea of implementing this using JSF will be really appreciated.
You should use a composite component, you can pass as many parameters as you want and customize it accordingly using #{cc.attrs.param1} syntax. Here's a sample XHTML.
Composite component
<ui:component xmlns="http://www.w3.org/1999/xhtml" xmlns:c="http://java.sun.com/jsp/jstl/core" xmlns:u="http://java.sun.com/jsf/composite/ui" 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:s="http://jboss.org/seam/faces" xmlns:p="http://primefaces.org/ui" xmlns:cc="http://java.sun.com/jsf/composite">
<cc:interface>
<cc:attribute name="tableId" />
<cc:attribute name="param1" />
<cc:attribute name="param2" default="false" />
<cc:attribute name="param3" required="true" />
</cc:interface>
<cc:implementation>
<p:dataTable id="#{cc.attrs.tableId}" rendered="#{cc.attrs.param2}" value="#{cc.attrs.param1}" var="result" emptyMessage="#{messages['global.noItemsFound']}">
<ui:include src="#{cc.attrs.param3}" />
</p:dataTable>
</cc:implementation>
</ui:component>
Using <c:if test="#{not empty cc.attrs.param4}"> or rendered attributes you can further customize your component
View
Let's call your composite myList.xhtml, then you could call it:
<u:myList param1="#{backingbean.results}" param2="true" id="list1" param3="/items/columns.xhtml" />
and don't forget to put a header in your view:
xmlns:u="http://java.sun.com/jsf/composite/ui"
columns.xhtml
<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:s="http://jboss.org/seam/faces" xmlns:u="http://java.sun.com/jsf/composite/ui"
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:p="http://primefaces.org/ui">
<p:column headerText="Name">
<h:outputText value="#{result.name}" />
</p:column>
<p:column headerText="Salary">
<h:outputText value="#{result.salary}" />
</p:column>
<p:column headerText="Age">
<h:outputText value="#{result.age}" />
</p:column>
</ui:composition>
An alternative to including a separate view for columns would be using <p:columns> in composite component and passing another list containing columns data as a parameter. Dynamic Columns

Using id-attribute in JSF 2 composite component with targets

I am trying to create a JSF 2.1 composite component for a button:
<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:composite="http://java.sun.com/jsf/composite"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
xmlns:c="http://java.sun.com/jstl/core">
<composite:interface>
<composite:attribute name="id" required="true" type="java.lang.String" />
<composite:attribute name="label" required="true" type="java.lang.String" />
<composite:attribute name="action" method-signature="java.lang.String action()" targets="#{cc.attrs.id}" />
</composite:interface>
<composite:implementation>
<a4j:commandLink id="#{cc.attrs.id}">
<span style="linkButton"><h:outputText value="#{cc.attrs.label}" /></span>
</a4j:commandLink>
</composite:implementation>
</html>
The problem I have with this code is that it gives the following exception when the page is rendered:
java.lang.ClassCastException: javax.faces.component.UINamingContainer cannot be cast to javax.faces.component.ActionSource2
at com.sun.faces.application.view.FaceletViewHandlingStrategy$MethodRetargetHandlerManager$ActionRegargetHandler.retarget(FaceletViewHandlingStrategy.java:1536)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.retargetMethodExpressions(FaceletViewHandlingStrategy.java:689)
at com.sun.faces.facelets.tag.jsf.CompositeComponentTagHandler.applyNextHandler(CompositeComponentTagHandler.java:201)
at org.richfaces.view.facelets.html.BehaviorsAddingComponentHandlerWrapper.applyNextHandler(BehaviorsAddingComponentHandlerWrapper.java:53)
at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.apply(ComponentTagHandlerDelegateImpl.java:196)
...
When I replace the #{cc.attrs.id} in id and targets attribute with a defined String like myId then the component works as expected but this makes it not reusable in the same page and thus eliminates the wohle sense in creating a composite component in the first place.
Did I miss anything here?
In the JSF component tree, the #{cc.attrs.id} is already used by <cc:implementation> itself. You're not supposed to reuse any used component ID on another component. Your concrete functional requirement is unclear, the complaint "not reusable in the same page" makes really no sense as it works perfectly fine (have you actually tried it and investigated the produced HTML output?), so it's hard to understand what problem exactly you're facing. Perhaps you completely overlooked that composite components implicitly inherit from NamingContainer and already prepend their own id to those of children, like as <h:form>, <h:dataTable>, etc also do?
If your sole requirement is being able to reference the composite component from outside by ajax as in <f:ajax render="compositeId" />, then you need to wrap the body of <cc:implementation> in a plain vanilla HTML <span> or <div> as follows with the #{cc.clientId} instead:
<div id="#{cc.clientId}">
See also:
Rerendering composite component by ajax

Conditionally render element's attribute in a composite component

I have the following composite component:
<?xml version="1.0" encoding="UTF-8"?>
<ui:component xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui"
xmlns:fn="http://java.sun.com/jsp/jstl/functions"
xmlns:composite="http://java.sun.com/jsf/composite">
<composite:interface>
<composite:attribute required="true" name="field" />
<composite:attribute required="true" name="value" />
<composite:attribute required="false" name="size"/>
</composite:interface>
<composite:implementation>
...
<div class="wrapper">
<h:inputText value="#{cc.attrs.value}"
id="#{field.id}"
rendered="#{field.rendered}"
size="#{cc.attrs.size}">
</h:inputText>
<h:messages for="#{field.id}" styleClass="errorMessage"/>
</div>
...
</composite:implementation>
</ui:component>
The problem is that when I'm using this component without setting its size attribute, it still gets rendered as size=0 in the html input element.
What I want is to render the nested h:inputText's attribute only if it has a valid value (eg. not empty). Alternatively, I'd like to expose all attributes of the nested element if they are not overridden explicitly.
How would it be possible?
You can use JSTL <c:if> to build the view conditionally and <f:attribute> to specify an attribute separately:
<h:inputText ...>
<c:if test="#{not empty cc.attrs.size}">
<f:attribute name="size" value="#{cc.attrs.size}" />
</c:if>
</h:inputText>
An alternative is to specify a default for the composite component attribute:
<cc:attribute name="size" required="false" default="10" />
Additional to BalusC's post:
You must use
type="int" in the cc:attribute-tag :
cc:attribute name="maxlength" type="int"
I believe there is an alternate method for accessing attributes. I've used this with JSF 2 when accessing an attribute named with a java reserved keyword.
{cc.attrs['size']}

How to create a composite of existing components in JSF?

I'd like to know if it's possible to compose my own component (or call it Widget, Object).
I mean, instead of (for example) using h:panelGroup and a h:outputLabel inside it, make my own h:panelMarkzzz, as a composition of panelGroup and outputLabel.
Is it possible on JSF?
Yes, it's possible to create a composition of existing components like that.
Kickoff example:
/resources/foo/group.xhtml
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:cc="http://xmlns.jcp.org/jsf/composite">
<cc:interface>
<cc:attribute name="label" type="java.lang.String" required="true" />
</cc:interface>
<cc:implementation>
<h:panelGroup>
<h:outputLabel value="#{cc.attrs.label}" />
<cc:insertChildren />
</h:panelGroup>
</cc:implementation>
</html>
/test.xhtml
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:foo="http://xmlns.jcp.org/jsf/composite/foo">
<h:head>
<title>Test</title>
</h:head>
<h:body>
<foo:group label="Label value">
<h:outputText value="This will appear after label inside the panelgroup" />
</foo:group>
</h:body>
</html>
The /foo folder name is free to your taste and you can reference it in XML namespace as http://xmlns.jcp.org/jsf/composite/XXX. The XHTML filename is the tag name.
That said, composite components have performance implications and they should only be used when the functional requirement is not achievable using a simple include or tagfile. In your specific case, you'd better use a tagfile instead. A composite component is only worthy when you actually need it for the <cc:interface componentType="...">.
See also:
When to use <ui:include>, tag files, composite components and/or custom components?
Our composite component wiki page
JSF http://xmlns.jcp.org/jsf/composite tag documentation
Java EE 7 tutorial - Composite components
Java EE 7 tutorial - Advanced composite components
Perhaps you mean Composite Components?

Resources