I have two primefaces panel components in jsf page.I want to show some data on panels via clicking primefaces commandButton and show panel1 when page load.When clicking commandbutton,I do not want to show other panel.So I defined boolean variables in backing bean to use in visible property of panels.But it does not work.
Backing Bean:
#ManagedBean
#SessionScoped
public class Bean implements Serializable {
private boolean show;
#PostConstruct
public void init(){
this.show=true;
}
public void action_commandButton(){
this.show=false;
}
}
Jsf Page
<p:commandButton style="text-align: center;font-size:12px;"
action="#{bean.action_commandButton()}" value=""/>
<!--panel 1 -->
<p:panel visible="#{bean.show}">
<p:dataGrid>
<!-- data from datbase-->
</p:dataGrid>
</p:panel>
<!-- panel 2-->
<p:panel visible="#{!bean.show}">
<p:dataGrid>
<!-- data from datbase-->
</p:dataGrid>
</p:panel>
How to solve this problem?
Thanks in advance.
Related
I'm using PrimeFaces' p:fieldset component and I want to control, from my bean, either or not it's collapsed. I expected the collpased property to do this job, but this is not working.
On the other hand, a "binding" seems to correctly mirror the component's state:
My Bean
#Named
#RequestScoped
public class TestBean {
//with get/set
private boolean collapsed;
//with get/set
private Fieldset fieldset;
}
My page:
<h:form>
<p:fieldset
id="togglebleFieldset"
legend="Toggleable Fieldset"
toggleable="true"
binding="#{testBean.fieldset}"
collapsed="#{testBean.collapsed}">
fieldset content
<p:ajax event="toggle" update="#form"/>
</p:fieldset>
<h:outputText value="Value is never updated: #{testBean.collapsed}" />
<br/><h:outputText value="Binding correctly reflects the state: #{testBean.fieldset.collapsed}" />
</h:form>
For reasons beyond the scope of this question, using the binding solution will be a little bit more complicated to me.
Why isn't #{testBean.collapsed} being update with the component's collapsed value?
(Using versions 6.0 and 6.2 of PrimeFaces)
Primefaces 5.0, JSF 2.2, Wildfly 8.1
The following use case:
Click a command button in a view (with some parameters)
The bean method looks something up in the database - if necessary dialog1 is shown. In dialog1 there is a form and a command button.
The command button in dialog1 is clicked, the bean method looks something up in the database.
Dialog1 is closed and dialog2, depending on the result of the bean method, is shown.
bean1.java:
public void buttonClicked() {
Map<String, Object> options = new HashMap<>();
options.put("modal", true);
options.put("widgetVar", "dialog1");
options.put("id", "dlg1");
if(somethingTrue()) {
RequestContext.getCurrentInstance().openDialog("dialog1.xhtml", options, null);
}
}
Everything fine. Dialog1 shows up.
dialog1.xhtml:
<h:body>
<h:form>
<p:commandButton value="Button" actionListener="#{bean2.dialog1ButtonClicked}" />
</h:form>
</h:body>
bean2.java:
public void dialog1ButtonClicked() {
Map<String, Object> options = new HashMap<>();
options.put("modal", true);
options.put("widgetVar", "dialog2");
options.put("id", "dlg2");
if(somethingTrue()) {
RequestContext.getCurrentInstance().openDialog("dialog2.xhtml", options, null);
}
}
dialog2.xhtml:
<h:body>
The operation was successful.
</h:body>
Dialog2 shows up within dialog1!
How can I close dialog1 and show dialog2 NOT within dialog1?
I tried closing dialog1 with Primefaces Dialog Framework before opening dialog2:
RequestContext.getCurrentInstance().closeDialog(null);
RequestContext.getCurrentInstance().openDialog("dialog2.xhtml", options, null);
Dialog2 doesn't show up.
I tried opening dialog2 after the AJAX callback <p:ajax event="dialogReturn" listener="#{bean1.dialogClosed}"/>
Dialog2 doesn't show.
I tried the client side Java Script call: onclick="PF('dialog1').hide()"
Dialog2 still shows up nested into dialog1.
using onHide you can open another dialog like this.
<p:dialog class="userRegisterDialog" header="#{bean.dailogHeader}" modal="true" resizable="false" draggable="false" onHide="PF('dialog2').show();>
</p:dialog>
It also work when close dialog using escape key.
Solution:
Open just one dialog:
RequestContext.getCurrentInstance().openDialog("dialog1.xhtml", options, null);
The dialog flow is controlled by an ajax update of the main panel, where the rendered attribute is bound to a bean property and therefore completely controlled by the bean.
dialog1.xhtml:
<p:dialog class="userRegisterDialog" header="#{bean.dailogHeader}"
modal="true" resizable="false" draggable="false">
<p:ajax event="close" listener="#{bean2.closeRegistration}" update=":update"/>
<p:panel id="update">
<p:panel id="step1" rendered="#{bean.showStep1}">
<h:form>
<p:commandButton class="continueButton" value="Button1" actionListener="#{bean.doStep1}" update=":update"/>
</h:form>
</p:panel>
<p:panel id="step2" rendered="#{bean.showStep2}">
<h:form>
<p:commandButton class="closeButton" value="Button2" actionListener="#{bean.doStep2}" update=":update"/>
</h:form>
</p:panel>
</p:panel>
</p:dialog>
The dialog bean:
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
#ManagedBean
#ViewScoped
public class Bean implements Serializable
{
private boolean showStep1 = true;
private boolean showStep2 = false;
public void doStep1(ActionEvent actionEvent) {
if(doSomething())
{
setShowStep1(false);
setShowStep2(true);
}
}
public void doStep2(ActionEvent actionEvent) {
if(doSomething2())
{
RequestContext.getCurrentInstance().closeDialog(null);
}
}
// Getter and setter ...
}
Another bean for the dialog closing:
#ManagedBean
#RequestScoped
public class Bean2 implements Serializable {
public void closeRegistration() {
FacesContext.getCurrentInstance().getViewRoot().getViewMap().remove("bean");
}
}
The method closeRegistration removes the viewscoped bean. Therefore another call of the the dialog within the same page will start the dialog flow from the beginning.
we can close on dialog in onsuccess or onerror or oncomplete also. Check the image for your reference
Hello,
I'm putting ui:include inside h:panelGroup and rendering it dynamically when required.
The usual assumption and theory is, ManagedBean associated with the included page should not get initialized when ui:include is not rendered.
This is not happening when I use ui:repeat inside included page.
Here is a Example to repeat the Issue:
page.1.xhtml
<h:body>
<h:form>
<p:outputLabel value="#{mBeanOne.beanOnetxt}"/><br/>
</h:form>
<h:panelGroup rendered="false" layout="block">
<ui:include src="page2.xhtml"/>
</h:panelGroup>
</h:body>
MBeanOne.java
#ManagedBean
#ViewScoped
public class MBeanOne implements Serializable{
private String beanOnetxt;
public MBeanOne() {
System.out.println("MBeanOne - Constructor");
}
#PostConstruct
public void init(){
beanOnetxt = "This is Managed Bean 1";
System.out.println("MBeanOne - Postconstruct");
}
//SETTERS and GETTERS
}
page2.xhtml
<h:body>
<h:outputText value="#{mBeanTwo.beanTwotxt}"/><br/>
<ui:repeat var="var" value="#{mBeanTwo.versionList}">
<h:outputText value="#{var}"/><br/>
</ui:repeat>
</h:body>
MBeanTwo.java
#ManagedBean
#ViewScoped
public class MBeanTwo implements Serializable{
private String beanTwotxt;
private List<String> versionList;
public MBeanTwo() {
System.out.println("MBeanTwo - Constructor");
}
#PostConstruct
public void init(){
beanTwotxt = "This is Managed Bean 2";
versionList = new ArrayList<String>();
versionList.add("Playground");
versionList.add("Kestrel");
versionList.add("Merlin");
versionList.add("Tiger");
System.out.println("MBeanTwo - Postconstruct");
}
//SETTER and GETTER
}
As you can see in page1.xhtml I have use rendered="false" for h:paneGroup which encapsulates ui:include, but still MBeanTwo is getting initialized when I load page1.xhtml.
If I remove ui:repeat from page2.xhtml then MBeanTwo is not getting initialized.
Is this a bug in JSF, if so any workaround available?
Versions used and tested:
Primefaces 3.5
JSF 2.1.13 and 2.2.0-m05
The <ui:include /> piece is not relevant in your question, it could be everything done in the same view with identical behaviour.
Anyway, it seems that <ui:repeat /> tag doesn't check its parents rendered attributes before doing bean initialization. However, the mBeanTwo#getVersionList method never gets evaluated, just the managed bean is created. That could bring you to a slowdown if you perform data access when you construct your bean, but never should break your view. I'm able to reproduce the problem in Mojarra 2.1.x versions, however they have fixed it for 2.2.x latest minors.
Seems a Mojarra implementation bug rather than an expected behaviour.
See also:
JSF ui:repeat included by ui:include wrapped in h:panelGroup with conditional rendering... A mouthfull
composite component xhtml:
<composite:interface componentType="metroComponent">
<composite:attribute name="uniqueId" />
</composite:interface>
<composite:implementation>
<rich:panel width="100%" header="#{msgs['pages.metroEth.header2']}">
<table class="resData">
<tr>
<td class="labelLeft"><h:outputLabel id="optionLabelId"
value="#{msgs['pages.ccparams.serviceOption']}" /></td>
<td><h:inputText id="optionTextId"
binding="#{cc.serviceOption}" size="15" /> <h:message
for="ccvodTextId" style="color:red" /></td>
</table>
</rich:panel>
</composite:implementation>
</ui:composition>
component type implementation is as follow:
#FacesComponent (value="metroComponent")
public class HtmlMetroCC extends UIComponentBase implements NamingContainer {
UIInput serviceOption;
public UIInput getServiceOption() {
return serviceOption;
}
public void setServiceOption(UIInput serviceOption) {
this.serviceOption = serviceOption;
}
#Override
public String getFamily() {
return "javax.faces.NamingContainer";
}
}
there is also a backing bean which prepare panelGroup element with list of presented above composite components. i removed getters/setters for better reading
#ManagedBean (name="metroethernetBean")
#RequestScoped
public class MetroEthernetMBean implements IBean{
private MetroEthCCData metroCCData;
private HtmlPanelGroup metroCCPanel;
private List<HtmlMetroCC> metroCClist;
#PostConstruct
public void initBean(){
metroCClist = new ArrayList<HtmlMetroCC>();
metroCCPanel = new HtmlPanelGroup();
HtmlMetroCC initialMetroCC = new HtmlMetroCC();
metroCClist.add(initialMetroCC);
processMetroCCPanel();
}
private void processMetroCCPanel(){
metroCCPanel.getChildren().clear();
for (HtmlMetroCC comp: metroCClist){
metroCCPanel.getChildren().add(comp);
}
}
}
page fragment responsible for displaying panelGroup looks like this:
<h:panelGroup id="metroCCPanelGrouId" binding="#{metroethernetBean.metroCCPanel}" />
the question is, why my composite components are not presented on panel? it looks panel has no children added at all..
when I put it as follows on page:
<gui:metroCC />
then composite comp. is displayed properly on page. What i want to achive is a panel on page with composite components which can be added or removed dynamically by clickin add new or delete selected
There is a wrokaround, instead of binding dynamically created panel in menaged bean
<h:panelGroup id="metroCCPanelGrouId" binding="#{metroethernetBean.metroCCPanel}" />
use mBean to initialize list/add new/ remove and loop through it on page:
<h:panelGroup id="metroCCPanelGrouId">
<ui:repeat var="test" value="#{metroethernetBean.metroCClist}">
<gui:metroCC binding="#{test}" />
</ui:repeat>
</h:panelGroup>
BUT: still don't understand why doing it with my first aproach fails...... BaluC, where are you ;)
Why after selecting an item in this code, the cities component does not get rendered?
<h:form prependId="false">
<h:panelGrid columns="1">
<h:selectOneMenu value="#{enumBeanStatus.selectedRegion}">
<f:selectItems id="selectItem" value="#{enumBean.regions}" var="region" itemLabel="#{region.label}"/>
<f:ajax listener="#{enumBean.loadCities}" render="cities"/>
</h:selectOneMenu>
<h:outputText id="cities" value="#{enumBean.cities}"/>
</h:panelGrid>
</h:form>
It does send a POST with the selected Region, model gets updated correctly, but the <h:outputText> Component is not rendered.
One of the backing beans:
#Named
public class EnumBean {
private List<Region> regions;
private List<City> cities;
#Inject
EnumBeanStatus enumBeanStatus; //This one is CDI #ApplicationScoped & #Named
// Code...
public void loadCities(){
setCities(City.getCitiesByRegion(enumBeanStatus.getSelectedRegion()));
}
// Getters and Setters
}
Remove prependId="false" from the <h:form>. It prevents <f:ajax> from resolving the right component based on a relative client ID.
See also:
How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"
UIForm with prependId="false" breaks <f:ajax render>