I am a newbie on jsf i want to display the details of a question when i click on a h:link and to do so i need to pass the question id between two jsf pages (i have a detail page and another page that display a list of questions to display their details) but this id is of type Long so i need to convert it in order to be able to look for it in the database but i don't know how to do so.
I google it but the code i wrote after the search don't work. Here's the code
<p:dataList value="#{questionBean.questionsForums}" var="quests"
itemType="none">
<p:panel >
<f:facet name="header">
<h:outputText value="#{quests.nbupvote}"
style="margin-right:30px;color:#cdcdcd" class="voteBox" />
<h:outputText class="font-custom" value="#{quests.titre}" />
</f:facet>
<h:link value="Consulter Détails" outcome="question">
<f:param name="quesId" value="#{quests.quesPk}" >
</f:param>
</h:link>
</p:panel>
</p:dataList>
and this the code of the managedBean
private String quesPk;
private Question detailQuestion;
public Question getDetailQuestion() {
return detailQuestion=qDao.selectDetail(Long.valueOf(quesPk));
}
public void setDetailQuestion(Question detailQuestion) {
this.detailQuestion = detailQuestion;
}
And this in the log with the exception
2014-01-16T21:11:22.145+0100|Grave: Error Rendering View[/question.xhtml]
javax.el.ELException: /question.xhtml #52,24 value="#{questionBean.detailQuestion}": java.lang.NumberFormatException: null
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:114)
at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:194)
at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:182)
at javax.faces.component.UIData.getValue(UIData.java:732)
Caused by: javax.el.ELException: java.lang.NumberFormatException: null
at javax.el.BeanELResolver.getValue(BeanELResolver.java:368)
at com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:176)
at com.sun.faces.el.DemuxCompositeELResolver.getValue(DemuxCompositeELResolver.java:203)
at com.sun.el.parser.AstValue.getValue(AstValue.java:140)
at com.sun.el.parser.AstValue.getValue(AstValue.java:204)
at com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:226)
at org.jboss.weld.el.WeldValueExpression.getValue(WeldValueExpression.java:50)
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:109)
... 53 more
Caused by: java.lang.NumberFormatException: null
at java.lang.Long.parseLong(Long.java:404)
at java.lang.Long.valueOf(Long.java:540)
at com.portail.managedBeans.QuestionBean.getDetailQuestion(QuestionBean.java:33)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
2014-01-16T21:11:22.220+0100|Avertissement: StandardWrapperValve[Faces Servlet]: Servlet.service() for servlet Faces Servlet threw exception
java.lang.NumberFormatException: null
at java.lang.Long.parseLong(Long.java:404)
at java.lang.Long.valueOf(Long.java:540)
at com.portail.managedBeans.QuestionBean.getDetailQuestion(QuestionBean.java:33)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at javax.el.BeanELResolver.getValue(BeanELResolver.java:363)
And this is the code of the details of the question
<h:head>
<f:metadata>
<f:viewParam name="quesId" value="#{questionBean.quesPk}" converter="javax.faces.Long" />
</f:metadata>
</h:head>
<h:form>
<p:dataList value="#{questionBean.detailQuestion}" var="quests"
itemType="none">
<h:outputText value="1" style="margin-right:30px;color:#cdcdcd"
class="voteBox" />
<h3><h:outputText class="font-custom"
value="#{quests.titre}" /></h3><br/><p:separator></p:separator>
<h:outputText class="font-custom"
value="#{quests.contenu}" />
<div class="navfooter" style="margin-left: 20%">
<ul>
<li>Modifier</li>
<li style="margin-left: 40%">Auteur</li>
</ul>
</div>
</p:dataList>
I am using eclipse kepler and jsf2 and primefaces. If you know how it can be done please tell me
#ManagedProperty is not the right tool for the job of converting a submitted value and setting it as a bean property. HTTP request parameters are inherently strings. Better use <f:viewParam>, you can attach a converter to it like as you would do to <h:inputText>.
Source page:
<h:link value="Consulter Détails" outcome="question">
<f:param name="quesId" value="#{quests.quesPk}" />
</h:link>
Target page (question.xhtml):
<f:metadata>
<f:viewParam name="quesId" value="#{questionBean.quesPk}" converter="javax.faces.Long" />
</f:metadata>
With
private Long quesPk; // +setter
See also:
ViewParam vs #ManagedProperty(value = "#{param.id}")
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
Unrelated to the concrete problem, doing business logic in getter methods is a bad idea. Don't do that. Use <f:event type="preRenderView"> or <f:viewAction> listener method.
See also:
Why JSF calls getters multiple times
Related
it's a bit similar to this problem https://issues.jboss.org/browse/RF-11469
I have a template containing a composite defined like this:
<h:form id="transfer_list">
<ccs:criteriaPanel header="Critère de recherche"
filterAction="#{controller.filter()}">
<form:criteriaForm bean="#{controller.transferCriteria}"
rendered="#{! empty controller.transferSearchForm}"
mode="UPDATE"
controller="#{controller}" />
</ccs:criteriaPanel>
</h:form>
Controller is defined with a ui:param in the template child.
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
template="/pages/transfer/transferList.xhtml">
<ui:param name="controller" value="#{transferListOpenController}" />
</ui:composition>
Here is the composite impl (criteriaPanel):
<cc:interface>
<cc:attribute name="header" default="#{i18n['HEADER_SEARCH_CRITERIA']}" />
<cc:attribute name="filterAction" method-signature="java.lang.Object filter()" />
<cc:attribute name="update" default="#(.ui-datatable)" />
</cc:interface>
<cc:implementation>
<div id="#{cc.clientId}">
<p:panel header="#{cc.attrs.header}" toggleable="true">
<cc:insertChildren />
<f:facet name="footer">
<p:commandButton id="search_btn"
value="#{i18n['BUTTON_FILTER']}"
action="#{cc.attrs.filterAction}"
icon="ui-icon-search"
update="#{cc.attrs.update}" />
<p:commandButton value="#{i18n['BUTTON_CLEAR_FILTER']}"
action="#{cc.attrs.filterAction}"
process="#this"
immediate="true"
update="#{cc.attrs.update}">
<p:ajax update="#form" resetValues="true" />
</p:commandButton>
</f:facet>
<p:defaultCommand target="search_btn" />
</p:panel>
</div>
</cc:implementation>
Clicking on the button "filterAction" result into this:
javax.faces.FacesException: #{cc.attrs.filterAction}:
javax.el.PropertyNotFoundException: Target Unreachable, identifier
[controller] resolved to null at
com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:118)
at
org.primefaces.application.DialogActionListener.processAction(DialogActionListener.java:45)
at javax.faces.component.UICommand.broadcast(UICommand.java:315)
I use Tomcat 8.5 for this and Mojarra 2.2.13. It works if I don't put the whole thing in a composite component (criteriaPanel)
UPDATE
Sample available here: https://github.com/Rapster/primefaces-test/tree/issue-sof-45834296
Works fine with MyFaces 2.2.11 and Mojarra 2.2.8-23 and 2.3.2 (I don't know how impactful upgrading to 2.3 can be though...) From what I read here https://stackoverflow.com/a/42656386/4605161, Mojarra 2.2.8 is aimed for WebLogic but it seems I will need this one (and i'm running on Tomcat)
WORKAROUND
Writing this make it work (but that's a workaround i'd rather use template):
<ui:composition xmlns="http://www.w3.org/1999/xhtml">
<ui:param name="controller" value="#{testView}" />
<ui:decorate template="/template.xhtml">
</ui:decorate>
</ui:composition>
Funny thing is if I put ui:param inside ui:decorate I'll end up with the same exception
Should be fixed in 2.2.15, see github.com/javaserverfaces/mojarra/issues/4271
I am writing a JSF datepicker composite component that is backed by jquery-ui's datepicker.(I don't have the option of using component libraries)
I have gotten the functionality to work, but I am now trying to simplify the component's interface by removing unnecessary attributes.
One of the attributes exposed by my component is called "value". I expect the user of the component to provide an el reference here eg.
#{myCarBean.selectedCar}
What I have noticed is that the component only ever seems to read the attribute's value. The setter never seems to get invoked.
I managed to get around this by exposing this method as a clientBehaviour .
But now I have an actionListener that is invoked through this clientBehaviour(to set the value) as well as the "value" attribute which reads the value from #{cc.attrs.values}.
How can I have a single attribute that can both read/write the "value" attribute to the underlying managedBean provided by the using page?
Here is the code:
<ui:component xmlns="http://www.w3.org/1999/xhtml" xmlns:util="http://discovery.co.za/mytags" xmlns:c="http://java.sun.com/jsp/jstl/core" 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 componentType="modal">
<cc:attribute name="value" type="java.util.Date" shortDescription="An El expression representing the managed bean field to which the selected date will be wired."></cc:attribute>
<cc:attribute name="minYear" type="java.lang.Integer" shortDescription="An El expression representing a managed bean field which should return an Integer indicating the year component of the minDate"></cc:attribute>
<cc:attribute name="minMonth" type="java.lang.Integer" shortDescription="An El expression representing a managed bean field which should return an Integer indicating the month component of the minDate.(January is 0)"></cc:attribute>
<cc:attribute name="minDay" type="java.lang.Integer" shortDescription="An El expression representing a managed bean field which should return an Integer indicating the day component of the minDate."></cc:attribute>
<cc:attribute name="maxYear" type="java.lang.Integer" shortDescription="An El expression representing a managed bean field which should return an Integer indicating the year component of the maxDate"></cc:attribute>
<cc:attribute name="maxMonth" type="java.lang.Integer" shortDescription="An El expression representing a managed bean field which should return an Integer indicating the month component of the maxDate"></cc:attribute>
<cc:attribute name="maxDay" type="java.lang.Integer" shortDescription="An El expression representing a managed bean field which should return an Integer indicating the day component of the maxDate"></cc:attribute>
<cc:attribute name="render" type="java.lang.String" />
<cc:clientBehavior name="change" targets="#{cc.clientId}:dateInput" event="change" />
</cc:interface>
<cc:implementation>
<div id="#{cc.clientId}">
<h:inputText id="dateInput" value="#{cc.attrs.value}" styleClass="jquery-datepicker"
onclick="modifyDatePickerOptions('#{cc.attrs.clientId}', #{cc.attrs.minYear}, #{cc.attrs.minMonth}, #{cc.attrs.minDay}, #{cc.attrs.maxYear}, #{cc.attrs.maxMonth}, #{cc.attrs.maxDay} );">
<f:ajax execute="#form" event="change" render="#{cc.attrs.render}" />
</h:inputText>
</div>
</cc:implementation>
And the using page :
<h:form id="datePickerForm">
<my:datepicker render=":datePickerForm:datePickerAjax" value="#{datePickerBean.selectedDate}" minYear="1999" minMonth="0" minDay="1" maxYear="2019" maxMonth="0" maxDay="1">
<f:ajax event="change" listener="#{datePickerBean.selectedDate}" />
</my:datepicker>
<h:panelGroup id="datePickerAjax" layout="block">
<br />
<b><h:outputText value="You selected : #{datePickerBean.selectedDate}" rendered="#{datePickerBean.selectedDate != null}" /></b>
</h:panelGroup>
</h:form>
You need to add a converter to your inputText field. You can nest an <f:convertDateTime/> tag in your inputText to achieve this. See convertDateTime for all the available attributes.
I've the following code snippet in my Facelet:
<h:commandLink id="cmdbtn">
<f:ajax event="click" execute="#form"
listener="#{screenShotBean.takeScreenshot}" />
</h:commandLink>
It works fine, but when I outcomment it like this,
<!-- <h:commandLink id="cmdbtn"> -->
<!-- <f:ajax event="click" execute="#form" -->
<!-- listener="#{screenShotBean.takeScreenshot}" /> -->
<!-- </h:commandLink> -->
then it throws the following exception:
javax.el.PropertyNotFoundException: Property 'takeScreenshot' not found on type monstage.test.com.ScreenShotBean
at javax.el.BeanELResolver$BeanProperties.get(BeanELResolver.java:237)
at javax.el.BeanELResolver$BeanProperties.access$400(BeanELResolver.java:214)
at javax.el.BeanELResolver.property(BeanELResolver.java:325)
at javax.el.BeanELResolver.getValue(BeanELResolver.java:85)
at com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:176)
at com.sun.faces.el.DemuxCompositeELResolver.getValue(DemuxCompositeELResolver.java:203)
at org.apache.el.parser.AstValue.getValue(AstValue.java:169)
at org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:189)
at com.sun.faces.facelets.el.ELText$ELTextVariable.toString(ELText.java:217)
at com.sun.faces.facelets.el.ELText$ELTextComposite.toString(ELText.java:157)
at com.sun.faces.facelets.compiler.CommentInstruction.write(CommentInstruction.java:77)
at com.sun.faces.facelets.compiler.UIInstructions.encodeBegin(UIInstructions.java:82)
at com.sun.faces.facelets.compiler.UILeaf.encodeAll(UILeaf.java:183)
at javax.faces.render.Renderer.encodeChildren(Renderer.java:168)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:845)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1779)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1782)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:424)
at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:125)
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:121)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:594)
When I change the method expression with parentheses as below,
<!-- <h:commandLink id="cmdbtn"> -->
<!-- <f:ajax event="click" execute="#form" -->
<!-- listener="#{screenShotBean.takeScreenshot()}" /> -->
<!-- </h:commandLink> -->
Then doesn't throw the exception, but it's still invoked.
How is this caused and how can I solve it?
Look closer at the stack trace. Here's the relevant part:
...
org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:189)
com.sun.faces.facelets.el.ELText$ELTextVariable.toString(ELText.java:217)
com.sun.faces.facelets.el.ELText$ELTextComposite.toString(ELText.java:157)
com.sun.faces.facelets.compiler.CommentInstruction.write(CommentInstruction.java:77)
...
It's thus evaluating EL in a comment block (recognizable by CommentInstruction). A comment block is considered as template text. Facelets evaluates by default also EL #{} in template text. It's like as if you're writing <p>#{screenShotBean.takeScreenshot}</p> without any JSF tag.
You've several options:
Remove the comment block altogether.
Escape EL expressions in the comment by prefixing it with \ as in
\#{screenShotBean.takeScreenshot}
so that they won't be evaluated.
Wrap the entire comment block in <ui:remove> so that it doesn't appear in the component tree (nor in the generated HTML output).
Disable parsing of all comments by Facelets by adding the following context parameter to web.xml:
<context-param>
<param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name>
<param-value>true</param-value>
</context-param>
Note that no one comment will end up in generated HTML output this way.
In addition to the options BalusC already provided you could also add the attribute rendered="false" to your commandLink.
If you have several components you want to be able to toggle quickly, you might want to consider creating a debug property in a bean or use the project stage:
rendered="#{facesContext.application.projectStage == 'Development'}"
You could also use the context parameter that skips comments in your web.xml.
This is the parâmeter:
javax.faces.FACELETS_SKIP_COMMENTS
I'm attempting to use a special PrimeFaces data exporter implementation as being used in this answer:
https://stackoverflow.com/a/14413932/396732
Our use case however is a little more complex, e.g. using Facelets to show the respective datatable for export, which has row expansions with sub tables in them.
insiderListManagerDialogs.xhtml:
<ui:include src="insiderListManagerListDialog.xhtml">
<ui:param name="idPrefix" value="il-emp" />
<ui:param name="widgetVarPrefix" value="ilEmp" />
<ui:param name="dialogTitle" value="#{msg['entity.employee.internal.plural.label']}" />
<ui:param name="mapPropertyName" value="insiderListEmployeesMap" />
<ui:param name="sortColumn" value="#{ent.lastTime}" />
<ui:param name="keyColumnsXhtml" value="listDialogInsiderListKeyColumns.xhtml" />
<ui:param name="valueColumnsXhtml" value="listDialogEmployeeValueColumns.xhtml" />
</ui:include>
insiderListManagerListDialog.xhtml:
<p:dialog id="#{idPrefix}-il-view-dialog"
widgetVar="#{widgetVarPrefix}Dialog"
header="#{dialogTitle}"
modal="true"
resizable="false"
appendToBody="true"
onShow="resetFilterInput( '#{idPrefix}' );"
width="1000"
height="750">
<h:form id="#{idPrefix}-il-view-form">
<p:dataTable id="list-entities"
widgetVar="listEntitiesTable"
binding="#{table}"
value="#{insiderListManager.listInstances}"
var="key"
scrollable="true"
scrollHeight="625"
scrollWidth="985"
resizableColumns="true"
expandedRow="#{insiderListManager.listEntitiesRowTogglerOpen}"
filteredValue="#{insiderListManager.filteredEntities}"
sortBy="#{sortColumn}"
styleClass="bx-datatable-header-hidden-m"
tyle="width: 970px;">
<f:facet name="header">
<p:inputText id="globalFilter"
onkeypress="if (event.keyCode == 13) { listEntitiesTable.filter(); return false;}"
size="70"
styleClass="bx-dt-header-element" />
<p:commandButton id="search-btn"
icon="ui-icon bx-icon-search"
value="#{msg['common.action.search.label']}"
process="#this"
onclick="listEntitiesTable.filter(); return false;"
styleClass="bx-dt-header-element" />
<p:commandButton title="#{msg['common.action.excelExport.all.hint']}"
icon="ui-icon bx-icon-excel"
action="#{insiderListManager.exportXls( table )}"
ajax="false"
styleClass="bx-button-border bx-dt-header-element" />
<div class="bx-clear-float" />
</f:facet>
<p:column width="15"
resizable="false">
...
<p:rowExpansion>
<p:dataTable value="#{insiderListManager[mapPropertyName].get(key)}"
var="value">
<ui:include src="#{valueColumnsXhtml}" />
</p:dataTable>
</p:rowExpansion>
</p:dataTable>
<h:panelGroup id="button-panel" layout="block" styleClass="left-button-panel mt-5px">
<p:commandButton id="toggle-button"
icon="#{insiderListManager.listEntitiesRowTogglerOpen ? 'ui-icon ui-icon-circle-triangle-e' : 'ui-icon ui-icon-circle-triangle-s'}"
value="#{insiderListManager.listEntitiesRowTogglerOpen ? msg['common.action.collapseAll.label'] : msg['common.action.expandAll.label']}"
process="#this"
update="#form">
<f:setPropertyActionListener target="#{insiderListManager.listEntitiesRowTogglerOpen}"
value="#{not insiderListManager.listEntitiesRowTogglerOpen}" />
</p:commandButton>
</h:panelGroup>
</h:form>
</p:dialog>
Note the
<p:commandButton title="..."
icon="ui-icon bx-icon-excel"
action="#{insiderListManager.exportXls( table )}"
... />
which is using the bound data table as described in the link posted at the top.
We are using JSF 2.1 (Mojarra 2.1.22 - and we cannot switch to MyFaces) which allows expressions to construct IDs like #{idPrefix}-il-view-dialog from a <ui:param name="idPrefix" value="il-emp" />.
However, we are getting ID uniqueness exception:
Caused by: java.lang.IllegalStateException: Component ID il-emp-il-view-form:list-entities:globalFilter has already been found in the view.
at com.sun.faces.util.Util.checkIdUniqueness(Util.java:846)
at com.sun.faces.util.Util.checkIdUniqueness(Util.java:830)
at com.sun.faces.util.Util.checkIdUniqueness(Util.java:830)
at com.sun.faces.util.Util.checkIdUniqueness(Util.java:830)
at com.sun.faces.util.Util.checkIdUniqueness(Util.java:830)
at com.sun.faces.util.Util.checkIdUniqueness(Util.java:830)
at com.sun.faces.util.Util.checkIdUniqueness(Util.java:830)
at com.sun.faces.util.Util.checkIdUniqueness(Util.java:830)
at com.sun.faces.application.view.StateManagementStrategyImpl.saveView(StateManagementStrategyImpl.java:144)
at com.sun.faces.application.StateManagerImpl.saveView(StateManagerImpl.java:133)
at com.sun.faces.application.view.WriteBehindStateWriter.flushToWriter(WriteBehindStateWriter.java:225)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:419)
at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:131)
at com.ocpsoft.pretty.faces.application.PrettyViewHandler.renderView(PrettyViewHandler.java:163)
at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:288)
at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:288)
at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:288)
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:121)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:594)
... 49 more
Same happens to other buttons with explicit IDs if omitted, e.g. the search button (<p:commandButton id="search-btn" ...).
QUESTION:
Why is this happening and how can we avoid this problem when we are bound to using PrimeFaces dialogs for each use case displayed? (we have more than one dialog)
Note that when removing the <p:dataTable ... binding="..." the page works correctly.
You're basically binding physically different <p:dataTable> components to one and same EL variable. If this EL variable is not null (i.e. already set by a previous component in the same view), then JSF will reuse it instead of creating a new one, and override all of its attributes during view build time, resulting in "weird" behavior during view render time and potential duplicate component ID errors during state saving.
In your specific case, you can use UIComponent#getNamingContainer() to directly reference the parent <p:dataTable> component from inside a child component.
<p:dataTable ... (NO binding!)>
...
<p:comandButton ... action="#{bean.exportXls(component.namingContainer)}" />
Might it happen that it's nested in another NamingContainer component, then you need to use #{component.namingContainer.parent.namingContainer} instead. And so forth for multiple ones.
Currently I'm trying to implement webpart technology with JavaServer Faces 2.0 with Facelets view technology for educational purposes. I have created facelet templates, facelet custom components and made a few facelet "template" clients. But in one thing I'm stuck. I can't dynamically load controls and put them cc:attributes.
If I have a page for example with static text or bind it with ManagedBean the property ui:include everything works well.
<ui:define name="right-column">
right-column asd
<h:link outcome="asdf" value="link_get">
<f:param name="aa" value="123" />
<f:param name="a" value="123 dd + 20" />
</h:link>
<h:commandLink action="asdf?faces-redirect=true" value="asdf">
<f:param name="aa" value="123" />
</h:commandLink><br />
<ui:include src="./resources/Controls/CategoryTree.xhtml"/><br />
This works even if I put src with MenageBean property.
<ui:include src="#{browseProducts.incudePath}"/>
</ui:define>
Here is my facelet control (data binding is inside this control within #{TreeBean.root}:
<!-- NO INTERFACE -->
<cc:interface>
</cc:interface>
<!-- IMPLEMENTATION -->
<cc:implementation>
<!-- This is a very simply scaffolding for Category Three Control.
-->
<p:tree value="#{TreeBean.root}" var="node"
expandAnim="FADE_IN" collapseAnim="FADE_OUT">
<p:treeNode>
<h:outputText value="#{node}" />
</p:treeNode>
</p:tree>
</cc:implementation>
But I have problem when ui:include points to a control with cc:attribute. I don't know how to initialize this attribute from backing bean and do "stuff".
For example I have this page:
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
template="./resources/layout/Template.xhtml"
xmlns:sc="http://java.sun.com/jsf/composite/Controls">
<ui:define name="right-column">
<sc:dummy ItemCount="10" />
<ui:include src="./resources/Controls/dummy.xhtml" />
</ui:define>
</ui:composition>
Here goes the composite control:
<cc:interface>
<cc:attribute name="ItemCount" required="true"
shortDescription="This attribute is meaningful " />
</cc:interface>
<!-- IMPLEMENTATION -->
<cc:implementation>
<!-- How to pass ItemCount to my dummy bean to create so many items in
list as ItemCount value -->
<ui:repeat value="#{dummy.dummyList}" var="dummyItem">
<h:outputText value="#{dummyItem}" />
</ui:repeat>
</cc:implementation>
And backing bean code:
public ArrayList<String> getDummyList() {
//Here I try to get dummy list work.
dummyList = new ArrayList<String>(getDummyCount());
for (int i=0;i< getDummyCount();i++){
dummyList.add(i + "" + i);
}
return dummyList;
}
How can this be done?
I think you have two problems:
calling a method with parameter from a composite component
specifying some parameter to an included page
For 1., since jsf 2, you could call the method directly, specifying the parameter (which should be part of method signature):
<ui:repeat value="#{dummy.getDummyList(cc.attrs.dummyCode)}" var="dummyItem">
<h:outputText value="#{dummyItem}" />
</ui:repeat>
But I suspect you are trying to use a backing for something that it isn't designed for. Maybe you'll be interested in writing backing java code for your composite component, which is different. It's difficult to master if you are a beginner, though. I'd first try to design my pages and bean interactions differently. I don't know which problem you are trying to solve, but at first look, this solution looks too complicated.
For 2., you should have a look at ui:param. A quick google search gives me this: http://www.jsfcentral.com/articles/facelets_3.html