How to refer to components located in a different ui:include - jsf-2

On a facelet composed with different ui:include, what would be the best way to refer to a component located in ui:composition 2 from ui:composition 1?
Example:
fileA.xhtml
<ui:composition>
<p:commandButton value="OK" action="#{bean.foo}" update=":componentToUpdate"/>
</ui:composition>
fileB.xhtml
<ui:composition>
<p:panel id="componentToUpdate">
// ...
</p:panel>
</ui:composition>
Here, I'm "hardcoding" the id, "componentToUpdate". I thought of using a parameter:
<ui:include src="fileA.xhtml" >
<ui:param name="myParam" value="myId"/>
</ui:include>
fileB.xhtml
<ui:composition>
<p:panel id="#{myId}">
// ...
</p:panel>
</ui:composition>
Would it be interesting to have a bean that maintains all of these ids?
Hope I'm clear enough, thanks.

Related

ui:include parameter passing does not work when remote page is included

I have a basic UI (index.html) that is divided into Header, Footer and Content. The content-page is either on the same (local.xhtml) server like the index.html or on another (remote.xhtml) server.
Including the pages and dynamically reloading them with ajax works pretty good. But parameter passing only works on the local content page. The parameter is retrieved of a Bean called Login which also is on the same server as the index.html.
index.xhtml (excerpt):
<h:panelGroup id="content" layout="block">
<ui:include src="#{contentLoader.page}" >
<ui:param name="userName" value="#{login.userName}" />
</ui:include>
</h:panelGroup>
<h:form>
<f:ajax render=":content">
<ul>
<li><h:commandLink value="include1"
action="#{contentLoader.LocalPage}" /></li>
<li><h:commandLink value="include2"
action="#{contentLoader.remotePage}" /></li>
</ul>
</f:ajax>
</h:form>
local.xhtml
<h:body>
<ui:composition>
<h:form id="form">
<h:outputText value= "Local Page. Parameter is: #{userName}"/>
</h:form>
</ui:composition>
</h:body>
remote.xhtml
<h:body>
<ui:composition>
<h:form id="form">
<h:outputText value= "Remote Page. Parameter is: #{userName}"/>
</h:form>
</ui:composition>
</h:body>
local.xhtml prints out: "Local Page. Parameter is: MyUser"
remote.xhtml only: "Remote Page. Parameter is: "
I am using Glassfish4 as WebServer and JSF2
Thank you. The hints in the comments solved my Problem. For now this works fine for me:
<iframe> was solving my problem. Parameter passing within URL and JSF works brilliant.
Just "including" the remote page with <iframe src="#{myBean.Url}"></iframe> and reading the parameter with JSF Function "#{param['param1']}"
{myBean.Url} return a String in this format: localhost:8680/MyServiceservice/faces/myPage.html?param1=value1 with value1 being the parameter I want to transfer.

Composite method do not resolve parameter if in template

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

Duplicate id error with primefaces dialog in template

PF 3.5.10, Mojara 2.1.21, Omnifaces 1.5
I have Facelet-Template with p:menu and p:include for dialog
mytemplate.xhtml:
<h:form> ... <p:menubar>
<p:menuitem value="Start Dialog" oncomplete="mydialogwidget.show()"/>
<p:menuitem value="open another page" action="/app/mypage.xhtml?faces-redirect=true"/>
</p:menubar> ... </h:form>
<ui:insert name="content" />
<ui:include="/app/mydialog.xhtml" />
mydialog.xhtml:
<ui:composition>
<p:dialog widgetVar="mydialogwidget" ...>
<h:form>
<p:datatable binding="#{mybean.table}">
<p:column id="col_first"> ... </p:column>
...
<p:column id="col_last"> ... </p:colum>
</p:datatable>
</h:form>
</p:dialog>
</ui:composition>
mypage.xhtml:
<ui:composition template="/app/mytemplate.xhtml">
<ui:define name="content">
<h:form> ... </h:form>
</ui:define>
</ui:composition>
If I start mypage.xhtml form menue, I become JSF1007 error (Duplicate ids) The component tree will be written to my console. The simplified component tree output:
+id: mydialog
+id: mytable
+id: col_first <<=============
....
+id: col_last
+id:col_first <<========
The mydialog.xhtml will be included only once. The answer to question JSF with Primefaces Menu duplicate Id error? doesn't help me.
How can I aviod this error ? Where comes this error from ?
The prolbem was binding attribute on datatable. See also: Binding attribute causes duplicate component ID found in the view
SessionScoped component was used in multiple views.
I've used EL-table binding and then the problem was disappeared.

How to use <h:form> in <rich:tabPanel>

I'm developing my first JSF2 + Richfaces application and now I have this problem.
I have the following rich:tabPanel to which add and remove dynamically tab.
<h:form>
<rich:tabPanel id="tabsPanel" switchType="ajax" activeItem="#{tabsBean.activeTab}" >
<c:forEach var="tab" items="#{tabsBean.tabs}" styleClass="myRightPanel">
<rich:tab name="#{tab.name}" styleClass="myTab" >
<h:form id="#{tab.name}" >
<ui:include src="#{tab.pathDaIncludere}" />
</h:form>
</rich:tab>
</c:forEach>
</rich:tabPanel>
</h:form>
but to run I must add a <h:form> around each <rich:tab> otherwise the actions in the tabs will not work.
Is correct insert <h:form> in each tab?

Java facelets dynamic loading and composite component attributes

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

Resources