I have the following page, the price.xhtml has been included 3 times.
<f:subview id="include">
<ui:include src="/secure/menu/price.xhtml">
<ui:param name="info" value="#{msg['menu.step3.header']}" />
<ui:param name="domainKey" value="KEY1" />
</ui:include>
</f:subview>
<f:subview id="include2">
<ui:include src="/secure/menu/price.xhtml">
<ui:param name="info" value="#{msg['menu.step3.header']}" />
<ui:param name="domainKey" value="KEY3" />
</ui:include>
</f:subview>
<f:subview id="include2">
<ui:include src="/secure/menu/price.xhtml">
<ui:param name="info" value="#{msg['menu.step3.header']}" />
<ui:param name="domainKey" value="KEY2" />
</ui:include>
</f:subview>
My price.xhtml utilize a ViewScope Mbean (priceMBean), the problem is, JSF only instantiate a single mBean.
I want 3 instances of the priceMBean, how do i achieve this ?
Raphael.
For this typical use case it is better to use injection instead of creating N bean requested scope in the face config
BalusC answers is good and can be improved with DI and facelets.
#ManagedBean
#ViewScoped
public class Parent {
#Inject
private Child price1;
#Inject
private Child price2;
#Inject
private Child price3;
// ...
}
If Child class is always a dependent class of Parent, Child can be annotated as dependent "#Dependent". With dependent, you will have 3 distinct instances of Child class dependent of the lifecycle of the main bean (Parent).
And you can use the following template:
<f:subview id="include">
<ui:include src="/secure/menu/price.xhtml">
<ui:param name="info" value="#{msg['menu.step3.header']}"/>
<ui:param name="domainKey" value="KEY1"/>
<ui:param name="price" value="#{priceMBean.price1}"/>
</ui:include>
</f:subview>
<f:subview id="include2">
<ui:include src="/secure/menu/price.xhtml">
<ui:param name="info" value="#{msg['menu.step3.header']}"/>
<ui:param name="domainKey" value="KEY3"/>
<ui:param name="price" value="#{priceMBean.price2}"/>
</ui:include>
</f:subview>
<f:subview id="include2">
<ui:include src="/secure/menu/price.xhtml">
<ui:param name="info" value="#{msg['menu.step3.header']}"/>
<ui:param name="domainKey" value="KEY2"/>
<ui:param name="price" value="#{priceMBean.price3}"/>
</ui:include>
</f:subview>
Related
I have 3 files:
main.xhtml
<ui:include src="included.xhtml">
<ui:param name="bean" value="#{invoices}" />
<ui:param name="method" value="initExchange" />
</ui:include>
included.xhtml
<s:compositeComponent bean="#{bean}" beanMethod="#{method}"
buttonActionListener="#{bean[method]()}" />
compositeComponent.xhtml
<cc:interface>
<cc:attribute name="bean" />
<cc:attribute name="beanMethod" />
<cc:attribute name="buttonActionListener" method-signature="void f()" />
</cc:interface>
<cc:implementation>
<h:outputText value="#{cc.attrs.bean}" />
<h:outputText value="#{cc.attrs.beanMethod}" />
<p:commandButton actionListener="#{cc.attrs.buttonActionListener}" />
h:outputTexts are OK. But clicking on button gives exception:
Target Unreachable, identifier 'bean' resolved to null
How to pass the method to button's actionListener?
It works when actionListener in composite component is written as bean[method] like in included.xhtml:
<p:commandButton actionListener="#{cc.attrs.bean[cc.attrs.beanMethod]}" />
So generally passing method attributes through multiple stages should always be done by separate bean and method rather then one attribute with 'method-signature'.
I'm using Primefaces 5.1.When I press button dynamically include page but it not working.I try below code:
page.xhtml
<f:subview id="userView">
<h:form id="userId">
<p:commandButton id="userButton" value="Import"
action="user.pageAction" update=":userView:dynamicPanel"/>
</h:form>
<p:panel id="dynamicPanel">
<ui:include src="${BranchDetails.PagePath}" />
</p:panel>
</f:subview>
pageClass.java
public void pageAction()
{
pagePath="/pages/userMangement/userDetail.xhtml"
}
I try update facescontext and request context also but it not include page
FacesContext.getCurrentInstance().getPartialViewContext().getRenderIds().add(":dynamicPanel"); and
RequestContext.getCurrentInstance().update(":dynamicPanel")
I try replace (:dyanamicPanel to dynamicPanel) update but that also not working.
You use action the wrong
<f:subview id="userView">
<h:form id="userId">
<p:commandButton id="userButton" value="Import"
action="user.pageAction" update=":userView:dynamicPanel"/>
</h:form>
<p:panel id="dynamicPanel">
<ui:include src="${BranchDetails.PagePath}" />
</p:panel>
</f:subview>
correct
<f:subview id="userView">
<h:form id="userId">
<p:commandButton id="userButton" value="Import"
action="#{user.pageAction}" update=":dynamicPanel"/>
</h:form>
<p:panel id="dynamicPanel">
<ui:include src="${BranchDetails.PagePath}" />
</p:panel>
</f:subview>
I have a page with the following params:
<f:metadata>
<f:event type="preRenderView" listener="#{busquedaBean.init}" />
<f:viewParam name="k" value="#{busquedaBean.keyword}" />
<f:viewParam name="categoryId" value="#{busquedaBean.categoryId}" />
<f:viewParam name="minprice" value="#{busquedaBean.minPrice}" />
<f:viewParam name="maxprice" value="#{busquedaBean.maxPrice}" />
</f:metadata>
All of them are optional. I need to do 2 things, which I wasn't able to do so far:
1) Add new params (keeping the previous params). This is what I tried for adding price params:
<h:outputText value="Precio diario" />
<o:form includeRequestParams="true">
<h:outputText value="min: " />
<p:inputText id="min" value="#{busquedaBean.minPrice}" />
<h:outputText value="max: " />
<p:inputText id="max" value="#{busquedaBean.maxPrice}" />
<p:commandButton icon="ui-icon-search" ajax="false">
<f:param name="minprice" value="#{busquedaBean.minPrice}" />
<f:param name="maxprice" value="#{busquedaBean.maxPrice}" />
</p:commandButton>
</o:form>
This basically works but the problem is that the URL is not updated. if the params in the URL were ?minprice=10&maxprice=200 and I update those values, the url remains the same. if these params were not included in the url, they won't be added and the filter won't work.
2) Updating the value of a param:
When categoryId is not empty, I want to show a button that will clear this param. This is what I tried:
<p:button outcome="/busqueda" includeViewParams="true" >
<f:param name="categoryId=" value="" />
</p:button>
But this button makes a GET to this URL: /busqueda/?categoryId=%3D&categoryId=1
The categoryId param appears twice. How can I just update the existing param?
I'm using MyFaces 2.1.14, Tomcat 7, Primefaces 4.0, Omnifaces
Thanks!
I was looking at this in the wrong way. includeViewParams=true will make the request include all the params declared in f:metadata with the current values. if such value is null, then the parameter is not included.
So.. to add price params:
<h:form >
<h:outputText value="$ " />
<p:inputText id="min" value="#{busquedaBean.minPrice}"/>
<h:outputText value=" a $ " />
<p:inputText id="max" value="#{busquedaBean.maxPrice}"/>
<p:commandButton icon="ui-icon-search" ajax="false" action="/busqueda?faces-redirect=true&includeViewParams=true" />
</h:form>
And to remove a param:
<p:commandButton action="#{busquedaBean.removeCategory}" ajax="false" icon="ui-icon-close" />
In the backing bean:
public String removeCategory() {
categoryId = null;
return "/busqueda?faces-redirect=true&includeViewParams=true";
}
Am trying to create a composite component that will display the values as overlaypanel. But it returns the below error;
Cannot find component 'j_idt58:reviewDataTable:0:overrideCol' in view
overrideVersionDetails.xhtml:(composite component)
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:p="http://primefaces.org/ui"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:fn="http://java.sun.com/jsp/jstl/functions"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<cc:interface>
<cc:attribute name="forId" type="java.lang.String" required="true" />
<cc:attribute name="forValue" type="java.lang.Object" />
</cc:interface>
<cc:implementation>
<p:overlayPanel for="#{cc.attrs.forId}" my="left bottom">
#{cc.attrs.forValue}
</p:overlayPanel>
</cc:implementation>
</ui:composition>
Its used in another page:
<h:form>
....
...
<p:dataTable .....>
....
<p:column sortBy="#{dto.isSameCycleOverride}" width="100">
<f:facet name="header">
Override
</f:facet>
<h:commandLink id="overrideCol" binding="#{overrideCol}"
value="#{(dto.isSameCycleOverride) ? 'Yes' : 'No'}" />
<comp:overrideVersionDetails forId="#{overrideCol.clientId}"
forValue="#{dto.message}" />
</p:column>
....
</p:dataTable>
</h:form>
Any help is really appreciated.
I don't work with Primefaces, but with RichFaces I would use :
<comp:overrideVersionDetails forId="#{rich:clientId('overrideCol')}"
forValue="#{dto.message}" />
to do what you want.
With a little Help from SO :
Rich Faces rich:clientId in Primefaces?
it seems you can do this :
...
<h:commandLink id="overrideCol" value="#{(dto.isSameCycleOverride) ? 'Yes' : 'No'}" />
<comp:overrideVersionDetails forId="#{p:component('overrideCol')}"
forValue="#{dto.message}" />
...
Now to see if this works better than the use of binding in a dataTable...
I'm trying to render a different <h:form> using <a4j:jsFunction> in some other form. However its not working. The code I've implemented is as follows:
<t:div style="display:table-row; ">
<a4j:region>
<t:div style="display:table-cell; border:1px solid #608AA9;">
<h:form id="accordForm">
<rich:accordion id="accordId" switchType="client" activeItem="#{projectCreation.activeTab}">
<c:forEach var="proj" items="#{projectCreation.projects}">
<rich:accordionItem name="#{proj.description}">
<f:facet name="header">#{proj.description}</f:facet>
<h:form id="moduleAccord" rendered="#{proj.childCount>0}">
<rich:accordion id="moduleAccordId" switchType="client" activeItem="#{projectCreation.activeModuleTab}" onitemchange="moduleAccordionChange();">
<a4j:jsFunction name="moduleAccordionChange" execute="#all" render="#all" action="#{projectCreation.accordionItemChange}" />
<c:forEach var="mdle" items="#{proj.modules}">
<rich:accordionItem id="module#{mdle.id}" name="#{mdle.description}">
<f:facet name="header">#{mdle.description}</f:facet>
<h:form id="formodule#{mdle.id}" rendered="#{mdle.childCount>0}">
<t:dataList id="subModuleList" var="subMdle" value="#{mdle.subModules}" layout="unorderedList">
<a4j:commandButton id="subModuleCmd" value="#{subMdle.description}" action="#{projectCreation.fetchSubModuleDetails}">
<f:param name="subModuleId" value="#{subMdle.id}" />
</a4j:commandButton>
</t:dataList>
</h:form>
</rich:accordionItem>
</c:forEach>
</rich:accordion>
</h:form>
</rich:accordionItem>
</c:forEach>
</rich:accordion>
</h:form>
</t:div>
</a4j:region>
<h:form id="rightContent">
<t:div id="rightContentDiv">
<h:outputText id="selectedPage" value="#{projectCreation.creationModel.selectedPage}" />
<t:div id="projectDiv" style="display:table-cell;" rendered="#{projectCreation.creationModel.selectedPage=='Project'}">
<a4j:outputPanel ajaxRendered="true">
<ui:include src="/WEB-INF/facelets/project/editProject.xhtml"/>
</a4j:outputPanel>
</t:div>
<t:div id="moduleDiv" style="display:table-cell;" rendered="#{projectCreation.creationModel.selectedPage=='Module'}">
<a4j:outputPanel ajaxRendered="true">
<ui:include src="/WEB-INF/facelets/project/addModule.xhtml"/>
</a4j:outputPanel>
</t:div>
</t:div>
</h:form>
</t:div>
I'm trying to change the rendered page on selection of nested accordion module. I've checked in log that its working fine in controller but its not working as expected on facelet. Its working when I use switchType="server" however it reloads the page completely and I just want to render the rightContent form.
Have a look at this showcase example:
http://showcase.richfaces.org/richfaces/component-sample.jsf?demo=accordion&sample=dynamic&skin=blueSky
Do not nest forms, HTML does not support this !
How to use <h:form> in JSF page? Single form? Multiple forms? Nested forms?