When using MyFaces, I'm having trouble using ui:insert to insert a converter into a template component. The JSF implementation complains the the parent of my convertdateTime is not of the right type:
Parent not composite component or an instance of ValueHolder: org.primefaces.component.fieldset.Fieldset#6559fbd6
It seemingly then checks a Fieldset (which is a parent of a parent in my case)
<my:outputTextWithLabel id="creationdate" label="#{msg.common_datecreated}" value="#{bean.date}">
<my2:convertDateTime/>
</my:outputTextWithLabel>
My outputTextWithLabel components looks like this:
<!DOCTYPE html>
<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:p="http://primefaces.org/ui" xmlns:jsf="http://xmlns.jcp.org/jsf">
<ui:composition>
<h:panelGroup rendered="#{rendered or empty rendered}">
<p:outputLabel for="#{id}" value="#{label}" />
<div class="ui-inputfield ui-inputtext ui-widget ui-state-default ui-corner-all">
<h:outputText id="#{id}" value="#{value}">
<ui:insert/>
</h:outputText>
</div>
</h:panelGroup>
</ui:composition>
</html>
This code works fine with Mojarra...
So, just for clarity: isn't this supposed to work? Is Mojarra correct, or MyFaces? And what could be done here instead?
Related
I have a composite component with a dataScroller inside (tomahawk). In my xhtml I tried to use this component but I receive an error:
java.lang.IllegalArgumentException: could not find UIData referenced by attribute dataScroller#for = 'myTable'
The component:
<!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:composite="http://java.sun.com/jsf/composite"
xmlns:t="http://myfaces.apache.org/tomahawk">
<composite:interface>
<composite:attribute name="for" targets="scroll"></composite:attribute>
<composite:attribute name="paginatorMaxPages" />
</composite:interface>
<h:head>
</h:head>
<h:body>
<composite:implementation>
<div class="paginacao">
<t:dataScroller id="scroll" for="#{cc.attrs.for}"
styleClass="paginador" renderFacetsIfSinglePage="false"
pageIndexVar="numeroPagina" pageCountVar="quantidadePaginas"
rowsCountVar="quantidadeRegistros" paginator="true"
paginatorMaxPages="#{cc.attrs.paginatorMaxPages}"
paginatorTableClass="paginasPaginador"
paginatorActiveColumnClass="negrito">
<f:facet name="first">#{labels['paginacao.primeira']}</f:facet>
<f:facet name="previous">#{labels['paginacao.anterior']}</f:facet>
<f:facet name="next">#{labels['paginacao.proxima']}</f:facet>
<f:facet name="last">#{labels['paginacao.ultima']}</f:facet>
</t:dataScroller>
</div>
</composite:implementation>
</h:body>
</html>
My datatable:
<h:form>
...
<t:dataTable id="myTable" var="item" value="#{mBean.lista}">
...
</t:dataTable>
...
</h:form>
<param:parametrosScroll id="dataScroller" for="myTable" paginatorMaxPages="5" />
To ensure reusability of multiple instances in the same view, composite components are inherently naming containers, like <h:form>, <h:dataTable>, etc. In your specific case, the relative client ID in for="myTable" will be searched in the context of <cc:implementation>, but there is no such component. Instead, it's outside the composite, in another naming container represented by <h:form>.
You've 2 options:
Pass an absolute client ID after having given the <h:form> a fixed ID.
for=":myForm:myTable"
Use a tagfile instead of a composite.
In the given case, I want to use a facelet with different ManagedBeans, so the regarding action-bean is given as an parameter:
<?xml version="1.0" encoding="UTF-8" ?>
<!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:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html" >
<h:body>
<ui:include src="ratings.xhtml" >
<ui:param name="createAction" value="#{myOneCreateAction}" />
<ui:param name="ratings" value="#{context.ratings}" />
</ui:include>
</h:body>
</html>
I'm giving the create action as parameter value="#{myOneCreateAction}".
Within that facelet is a component also being used several times on other pages - so I try to refactor it in a composite component.
<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:io="http://java.sun.com/jsf/composite/inoutComponents">
<ui:composition>
<rich:dataTable id="ratingTblId"
value="#{ratings}"
var="rating">
<rich:column>
<io:removeButton
id="removeButton"
actionMethod="#{createAction.removeRating}"
immediate="true"
render=":#{rich:clientId('ratingTblId')}" />
<h:commandButton
id="removeButton2"
actionListener="#{createAction.removeRating}"
immediate="true" >
<f:ajax render="ratingTblId" />
</h:commandButton>
</rich:column>
</rich:dataTable>
</ui:composition>
</html>
See, how the method is given as actionMethod="#{createAction.removeRating}" to the component. This component itself looks like following:
<ui:composition 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:cc="http://java.sun.com/jsf/composite">
<!-- INTERFACE -->
<cc:interface>
<cc:attribute
name="actionMethod"
targets="remove"
method-signature="void f(javax.faces.event.ActionEvent)"/>
<cc:attribute name="render" required="false" />
</cc:interface>
<!-- IMPLEMENTATION -->
<cc:implementation>
<h:commandButton
id="remove"
actionListener="#{cc.attrs.actionMethod}"
onclick="if (!confirm('Do you really?')) { return false; }">
<f:ajax execute="#this" render="#{cc.attrs.render}" />
</h:commandButton>
</cc:implementation>
</ui:composition>
and last but not least, the managed bean
Name("myOneCreateAction")
#Scope(ScopeType.CONVERSATION)
public class MyOneCreateAction {
...
public void removeRating(ActionEvent ev) {
// do something
}
...
}
Surprisingly, while the removeButton2 correctly jumps into the right function, the composite components version returns a
javax.faces.event.AbortProcessingException: Target Unreachable,
identifier 'createAction' resolved to null
instead. Am using Mojarra JSF 2.1.26 with Seam 2.3.1.CR1. There are no nested composite components. When replacing the composite component parameter to #{myOneCreateAction.removeRating}, it works like expected.
Has anybody seen this before? Am I blind? Any work-arounds known... ? Thanks in advance!
As a work-around I rewrote the component to give action bean and action method as two separate parameters resolving them as following
xhtml:
<io:removeButton
id="removeButton"
actionBean="#{createAction}"
actionMethod="removeRating"
immediate="true"
render=":#{rich:clientId('ratingTblId')}" />
composite component:
<ui:composition 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:cc="http://java.sun.com/jsf/composite">
<!-- INTERFACE -->
<cc:interface>
<cc:attribute name="actionBean" />
<cc:attribute name="actionMethod" />
<cc:attribute name="render" required="false" />
</cc:interface>
<!-- IMPLEMENTATION -->
<cc:implementation>
<h:commandButton
id="remove"
action="#{cc.attrs.actionBean[cc.attrs.actionMethod]}"
onclick="if (!confirm('Do you really?')) { return false; }">
<f:ajax execute="#this" render="#{cc.attrs.render}" />
</h:commandButton>
</cc:implementation>
</ui:composition>
also changing the action methods signature to return String instead of void. That does not look that super sexy anymore, but works. :-/
I was having the same issue, found out that it has been fixed on version 2.2.15:
https://github.com/javaserverfaces/mojarra/issues/4271
I have this composite component that based on what is selected in a drop down(STREET, PO BOX) renders either another composite component streetAddressUpdate or postalBoxAddressUpdate. Here is the code
<?xml version='1.0' encoding='UTF-8' ?>
<!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:cc="http://java.sun.com/jsf/composite"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:tad="http://java.sun.com/jsf/composite/tmr/ad"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:tmi="http://java.sun.com/jsf/composite/tmr/mi">
<!-- INTERFACE -->
<cc:interface>
<cc:attribute
name="title"
default="Postal address" />
<cc:attribute
name="postalAddress"
type="qdtmr.comp.cbui.address.fieldmodel.PostalAddress"
default="#{addressUpdate.postalAddress}"
required="true" />
</cc:interface>
<cc:implementation>
<ol class="questions">
<!-- Postal address type -->
<li><h:outputLabel for="postalAddressType">
<span class="label">#{tcum.postalAddressType}</span>
</h:outputLabel> <p:selectOneMenu
id="postalAddressType"
value="#{cc.attrs.postalAddress.postalAddressType}"
valueChangeListener="#{addressUpdate.changePostalAddress}">
<f:selectItems value="#{addressController.postalAddressTypesList}" />
<p:ajax
update=":#{cc.clientId}:postalAddressPanel, :#{cc.clientId}:poBoxPanel" />
</p:selectOneMenu></li>
<p:outputPanel id="postalAddressPanel">
<ui:fragment rendered="#{cc.attrs.postalAddress.postalAddressType == 'STREET'}">
<tad:streetAddressUpdate
streetAddress="#{cc.attrs.postalAddress.postalStreetAddress}"
title="" />
</ui:fragment>
<p:outputPanel id="poBoxPanel">
<ui:fragment rendered="#{cc.attrs.postalAddress.postalAddressType == 'POBOX'}">
<tad:postalBoxAddressUpdate
postalBoxAddress="#{cc.attrs.postalAddress.postalBoxAddress}" />
</ui:fragment>
</p:outputPanel>
</ol>
</cc:implementation>
</html>
The thing that is confusing me is that if I take out the ui:fragment tag, my values on the page make their way back to the postalStreetAddress/postalBoxAddress model beans, but with the ui:fragment in their, my values do not end up making to the postalStreetAddress/postalBoxAddress.
The reason I have the ui:fragment is because depending on the postalAdressType either the postalBoxAddressUpdate composite component will be used or the postalStreetAddressUpdate component will be used.
Any help will be greatly appreciated. I suspect its the ui:fragment
EDIT: I checked up taking out the ui:fragment and it does seem to be the culprit. I would really like to understand whats happening
Im currently experimenting with facelets in JSF 2.0.
I currently have a case where a common grid definition is used by 2 facelets,
differs only in some areas like the bean name, the list name, the title, the grid id.
So what i have in mind is :
create template for that grid, making use of <ui:insert> in the areas that can differ between pages that use it
those 2 pages, make use of the template, supplying the parameters for the template with <ui:define>
Here is my gridTemplate.xhtml :
<?xml version="1.0" encoding="UTF-8"?>
<!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:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.prime.com.tr/ui"
xmlns:fn="http://java.sun.com/jsp/jstl/functions">
<h:head>
<title>#{msgs.title}</title>
</h:head>
<h:body>
<ui:composition template="/template/masterlayout.xhtml">
<p:dataTable id="<ui:insert name='gridId' />" var="rpb"
value="#{<ui:insert name='bean' />.<ui:insert name='list' />}">
<f:facet name="header">
<h3><ui:insert name='title' /></h3>
</f:facet>
.....
<f:facet name="footer">
#{fn:length(<ui:insert name='bean' />.<ui:insert name='list' />)} records<br />
</f:facet>
</p:dataTable>
</ui:composition>
</h:body>
</html>
And here's one of the facelet that makes use of the grid template :
<ui:composition template="gridTemplate.xhtml">
<ui:define name="gridId">grid</ui:define>
<ui:define name="bean">myBean</ui:define>
<ui:define name="list">myList</ui:define>
<ui:define name="title">my message !</ui:define>
</ui:composition>
And this experiment ends up with :
javax.servlet.ServletException: Error Parsing /gridTemplate.xhtml: Error Traced[line: 17] The value of attribute "id" associated with an element type "null" must not contain the '<' character.
javax.faces.webapp.FacesServlet.service(FacesServlet.java:325)
root cause
javax.faces.view.facelets.FaceletException: Error Parsing /gridTemplate.xhtml: Error Traced[line: 17] The value of attribute "id" associated with an element type "null" must not contain the '<' character.
com.sun.faces.facelets.compiler.SAXCompiler.doCompile(SAXCompiler.java:394)
com.sun.faces.facelets.compiler.SAXCompiler.doCompile(SAXCompiler.java:368)
com.sun.faces.facelets.compiler.Compiler.compile(Compiler.java:124)
com.sun.faces.facelets.impl.DefaultFaceletFactory.createFacelet(DefaultFaceletFactory.java:297)
com.sun.faces.facelets.impl.DefaultFaceletFactory.access$100(DefaultFaceletFactory.java:92)
com.sun.faces.facelets.impl.DefaultFaceletFactory$1.newInstance(DefaultFaceletFactory.java:162)
com.sun.faces.facelets.impl.DefaultFaceletFactory$1.newInstance(DefaultFaceletFactory.java:161)
com.sun.faces.facelets.impl.DefaultFaceletCache$1.newInstance(DefaultFaceletCache.java:83)
com.sun.faces.facelets.impl.DefaultFaceletCache$1.newInstance(DefaultFaceletCache.java:79)
com.sun.faces.util.ExpiringConcurrentCache$1.call(ExpiringConcurrentCache.java:99)
java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
java.util.concurrent.FutureTask.run(FutureTask.java:138)
I assume that this approach is not plausible, hence there should be a better solution for this kind of needs.
Should i use JSF Facelet Tag or JSF Composite Tag for this kind of case ?
Please share your opinions .. Thank you !
You have to make a composite component instead of template
<html 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>
<cc:attribute name="list"/>
<cc:attribute name="title"/>
</cc:interface>
<cc:implementation>
<p:dataTable id="#{cc.id}" var="rpb"
value="#{cc.attrs.list}">
<f:facet name="header">
<h3>#{cc.attrs.title}</h3>
</f:facet>
.....
<f:facet name="footer">
#{fn:length(cc.attrs.list)} records<br />
</f:facet>
</p:dataTable>
</cc:implementation>
</html>
This component has to be placed in a folder inside the resources folder, on the root of your webapp. The name of the component will be the same as the filename. So for this example lets call the component myComponent inside the /resources/components folder:
/resources/components/myComponent.xhtml
Then in any page you want to include the component you just have to do include the namespace of your component
xmlns:albert="http://java.sun.com/jsf/composite/components"
and render your component:
<albert:myComponent id="..." title="..." list=#{someBean.someList} />
I created a Facelet component to extend h:commandLink (to add some functionality and rounded corners).
<ui:composition 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">
<span class="btn-left btn-corners"> </span>
<span type="submit" class="submit">
<h:commandLink id="#{id}" value="#{label}" action="#{action}" />
</span>
<span class="btn-right btn-corners"> </span> </ui:composition>
My new component can be accessed using
<my:commandLink id="continue" label="continue" action="#{applyBacking.submit}"/>
and the Java code is
public String submit(){
...
}
However it gives me an error "ApplyBacking does not have the property submit".
I understand the reason for this error because while rendering my:commandLink, it tries to evaluate #{applyBacking.submit} to a property. Instead, I want the info about the method to the invoked (applyBacking.submit) to be passed to the template and evaluated while rendering h:commandLink.
Any suggestions?
Create a composite component instead (tutorial here), it enables you to define bean actions as attribtues.
Here's a kickoff example:
/resources/components/commandLink.xhtml
<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:cc="http://java.sun.com/jsf/composite">
<cc:interface>
<cc:attribute name="id" required="true" />
<cc:attribute name="label" required="true" />
<cc:attribute name="action" method-signature="java.lang.String action()" required="true" />
</cc:interface>
<cc:implementation>
<span class="btn-left btn-corners"> </span>
<span type="submit" class="submit">
<h:commandLink id="#{cc.attrs.id}" value="#{cc.attrs.label}" action="#{cc.attrs.action}" />
</span>
<span class="btn-right btn-corners"> </span>
</cc:implementation>
</ui:component>
/somepage.xhtml
<!DOCTYPE html>
<html lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:my="http://java.sun.com/jsf/composite/components">
<h:head>
<title>SO question 4608030</title>
</h:head>
<h:body>
<h:form>
<my:commandLink id="continue" label="continue" action="#{applyBacking.submit}"/>
</h:form>
</h:body>
</html>
By the way, I would personally prefer using JS/jQuery for the rounded corners part, for example the jQuery corner plugin. Just give your commandlink a specific styleClass and let JS do the magic.