Call PrimeFaces dialog from backing bean - jsf

I want when user in not logged-in, after clicking the Add To Card button, the Login dialog should appears.
Here is Book.xhtml:
<h:form>
<p:commandButton value="Add To Card"
actionListener="#{booksBean.orderBook()}"
class="QtyBtn">
<f:ajax execute="#form" rendered="#form"/>
</p:commandButton>
</h:form>
This is bean:
#Component
#Scope("session")
public class BooksBean implements Serializable {
...
public void orderBook() {
...
if (currentUser == null) { // show the login dialog
RequestContext.getCurrentInstance().openDialog("Login");
}
But Login.xhtml not opened.

First, what you want to do is to use PrimeFaces Dialog Framework(DF).
DF let's you open XHTML view in a dialog
Add this to your faces-config.xml
<application>
<action-listener>
org.primefaces.application.DialogActionListener
</action-listener>
<navigation-handler>
org.primefaces.application.DialogNavigationHandler
</navigation-handler>
<view-handler>
org.primefaces.application.DialogViewHandler
</view-handler>
</application>
Create your login.xhtml page as
any XHTML page.
Add the corresponding outcome to your faces-config.xml. For example,
<navigation-case>
<from-outcome>Login</from-outcome>
<to-view-id>/pages/login.xhtml</to-view-id>
<redirect />
</navigation-case>
Open the dialog with RequestContext.getCurrentInstance().openDialog("Login");
Note that the DF opens the new dialog inside a frame.

Related

Faces message stops working after page navigation

I have a problem with faces message rendering in portlet, deployed on HCL portal 9.5, which is on top of Websphere Application Server 9.0.5.7. Portlet has two pages and when I made first page navigation, faces message stops rendering.
First page html:
<div xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:portlet="http://java.sun.com/portlet_2_0"
xmlns:p="http://primefaces.org/ui">
<f:view>
<f:metadata>
<f:event listener="#{pc_TestJSF22View.init}" type="preRenderView"></f:event>
</f:metadata>
<h:head>
<h:outputScript library="primefaces" name="jquery/jquery.js" />
</h:head>
<h:body>
<h:form id="formMain" styleClass="form">
<p:commandButton id="btnTest" value="Test"
action="#{pc_TestJSF22View.doBtnTest}" />
<p:commandButton id="btnSecondPage" value="Second page"
action="#{pc_TestJSF22View.doBtnSecondPage}" ajax="false" />
<p:messages id="msgGlobal" globalOnly="true" showIcon="false">
<p:autoUpdate />
</p:messages>
</h:form>
</h:body>
</f:view>
First page request bean:
public class TestJSF22View extends PageCodeBase {
private TestSess testSess;
public void init() {
if (PrimeFaces.current().isAjaxRequest()) {
return;
}
try {
System.out.println("INIT method");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
// button action
public String doBtnSecondPage() {
return "testView2";
}
public String doBtnTest() {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("page 1 msg updated"));
return null;
}
protected TestSess getTestSess() {
if (testSess == null) {
testSess = (TestSess) getManagedBean("testSess");
}
return testSess;
}
}
Second page html:
<div xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:portlet="http://java.sun.com/portlet_2_0"
xmlns:p="http://primefaces.org/ui">
<f:view>
<f:metadata>
<f:event listener="#{pc_TestJSF22View2.init}" type="preRenderView"></f:event>
</f:metadata>
<h:head>
<h:outputScript library="primefaces" name="jquery/jquery.js" />
</h:head>
<h:body>
<h:form id="formMain" styleClass="form">
<p:commandButton id="btnFirstPage" value="First page"
action="#{pc_TestJSF22View2.doBtnFirstPage}" ajax="false" />
<p:commandButton id="btnMsg" value="Show message"
action="#{pc_TestJSF22View2.doBtnMsg}" />
<p:messages id="msgGlobal2" globalOnly="true" showIcon="false">
<p:autoUpdate />
</p:messages>
</h:form>
</h:body>
</f:view>
Second page request bean:
public class TestJSF22View2 extends PageCodeBase {
private TestSess2 testSess2;
public void init() {
if (PrimeFaces.current().isAjaxRequest()) {
return;
}
try {
System.out.println("INIT2 method");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
// button action
public String doBtnFirstPage() {
System.out.println("doBtnFirstPage method");
return "testView";
}
public String doBtnMsg() {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("page 2 msg updated"));
return null;
}
protected TestSess2 getTestSess2() {
if (testSess2 == null) {
testSess2 = (TestSess2) getManagedBean("testSess2");
}
return testSess2;
}
}
faces-config :
<?xml version='1.0' encoding='UTF-8'?>
<faces-config xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"
version="2.2">
<application>
<view-handler>com.ibm.faces20.portlet.FaceletPortletViewHandler</view-handler>
<el-resolver>com.ibm.faces20.portlet.PortletELResolver</el-resolver>
<resource-handler>com.ibm.faces20.portlet.httpbridge.PortletResourceHandler</resource-handler>
</application>
<factory>
<exception-handler-factory>org.primefaces.application.exceptionhandler.PrimeExceptionHandlerFactory</exception-handler-factory>
</factory>
<component>
<component-type>com.ibm.faces20.portlet.component.PortletActionURL</component-type>
<component-class>com.ibm.faces20.portlet.component.PortletActionURL</component-class>
</component>
<component>
<component-type>com.ibm.faces20.portlet.component.PortletResourceURL</component-type>
<component-class>com.ibm.faces20.portlet.component.PortletResourceURL</component-class>
</component>
<component>
<component-type>com.ibm.faces20.portlet.component.PortletRenderURL</component-type>
<component-class>com.ibm.faces20.portlet.component.PortletRenderURL</component-class>
</component>
<component>
<component-type>com.ibm.faces20.portlet.component.PortletParam</component-type>
<component-class>com.ibm.faces20.portlet.component.PortletParam</component-class>
</component>
<component>
<component-type>com.ibm.faces20.portlet.component.PortletProperty</component-type>
<component-class>com.ibm.faces20.portlet.component.PortletProperty</component-class>
</component>
<component>
<component-type>com.ibm.faces20.portlet.component.PortletNameSpace</component-type>
<component-class>com.ibm.faces20.portlet.component.PortletNameSpace</component-class>
</component>
<managed-bean>
<managed-bean-name>pc_TestJSF22View</managed-bean-name>
<managed-bean-class>pagecode.TestJSF22View</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>testSess</managed-bean-name>
<managed-bean-class>beans.TestSess</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>pc_TestJSF22View2</managed-bean-name>
<managed-bean-class>pagecode.TestJSF22View2</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>testSess2</managed-bean-name>
<managed-bean-class>beans.TestSess2</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
<render-kit>
<renderer>
<component-family>javax.faces.Output</component-family>
<renderer-type>com.ibm.faces20.portlet.tag.render.ActionURLTagRender</renderer-type>
<renderer-class>com.ibm.faces20.portlet.tag.render.ActionURLTagRender</renderer-class>
</renderer>
</render-kit>
<render-kit>
<renderer>
<component-family>javax.faces.Output</component-family>
<renderer-type>com.ibm.faces20.portlet.tag.render.ResourceURLTagRender</renderer-type>
<renderer-class>com.ibm.faces20.portlet.tag.render.ResourceURLTagRender</renderer-class>
</renderer>
</render-kit>
<render-kit>
<renderer>
<component-family>javax.faces.Output</component-family>
<renderer-type>com.ibm.faces20.portlet.tag.render.RenderURLTagRender</renderer-type>
<renderer-class>com.ibm.faces20.portlet.tag.render.RenderURLTagRender</renderer-class>
</renderer>
</render-kit>
<render-kit>
<renderer>
<component-family>javax.faces.Output</component-family>
<renderer-type>com.ibm.faces20.portlet.tag.render.PortletNameSpaceTagRender</renderer-type>
<renderer-class>com.ibm.faces20.portlet.tag.render.PortletNameSpaceTagRender</renderer-class>
</renderer>
</render-kit>
<navigation-rule>
<from-view-id>/*</from-view-id>
<navigation-case>
<from-outcome>testView</from-outcome>
<to-view-id>/TestJSF22View.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/*</from-view-id>
<navigation-case>
<from-outcome>testView2</from-outcome>
<to-view-id>/TestJSF22View2.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
</faces-config>
So, if I illustrate my problem: When I first open portlet and first page is displayed, I click "Test" button, that displays faces message. Next, I navigate to second page and I click "Show message" button, which should display another message on second page, but it doesn't. I get the following warning:
There are some unhandled FacesMessages, this means not every FacesMessage had a chance to be rendered.
These unhandled FacesMessages are:
- page 2 msg updated
Even if I go back to the first page again and hit "Test" button one more time, message is not displayed and the same warning is what I get.
I never had problems with faces messages when I deployed portlets on IBM Websphere Portal Server 7 with JSF 2.0, but now when I run it on HCL portal 9.5 (JSF 2.2), I noticed this strange behavior.
Did I miss something while migrating to HCL portal?
Primefaces version is 7.0, p:messages usage seems ok to me. Could HCL portlet bridge cause that problem? Does anyone have experience with deploying JSF portlets on HCL Portal?
EDIT1:
I've just tried to deploy web application with identical code on Websphere Application Server 9 and it works like a charm. Based on that I believe there's some problem with HCL Portal.

Pass parameter to the backing bean of the new page while navigation

I use a commandLink to navigate to another page:
<t:commandLink action="go_orderForm" immediate="true">
<h:outputText value="#{order.number}" />
<t:updateActionListener property="#{orderForm.orderId}"
value="#{order.id}" />
</t:commandLink>
This is working and setting the value of order.id to the backing bean orderForm.orderId.
In another place, I use a commandButton to call an action in the backing bean of the current page and navigate after to the new page:
<h:commandButton value="Create Batch" action="#{orderList.createBatchOrder}" />
The action in the backing bean looks like:
public String createBatchOrder() {
// do something
return "go_orderForm";
}
The faces-config.xml contains
<navigation-rule>
<navigation-case>
<from-outcome>go_orderForm</from-outcome>
<to-view-id>/orderForm.jsp</to-view-id>
</navigation-case>
</navigation-rule>
How can I pass the parameter for orderForm.orderId when I navigate using the action in the backing bean?
Before redirect put your parameter to flash:
FacesContext.getCurrentInstance().getExternalContext().getFlash().put(key, value);
After redirect you may get it by:
FacesContext.getCurrentInstance().getExternalContext().getFlash().get(key);

PrimeFaces actionListener not calling bean

I am trying to mimic the PrimeFaces Dialog example. For some reason that I am not able to find, my PrimeFaces button does not seem to call the required managed bean method:
<h:form>
<p:commandButton value="Open" icon="ui-icon-extlink" actionListener="#{myController.createDialog()}" />
</h:form>
Managed bean:
#Named(value = "myController")
#ViewScoped
public class MyController implements Serializable {
public void createDialog() {
System.out.println("%%%%%%%%%%%%%%%%%%%%%%%%%");
...
The print statement is never executed, like if the Listener was not working. When I click the button, no response is given. No backend error, no JS error, nothing. I only see that some request is done because I log when a user passes the authorization layer. So something happens but seems to fail silently.
What I have tried:
Move the button to other places in the page
Use an id:
<p:commandButton id="ex" value="Open" icon="ui-icon-extlink" actionListener="#{myController.createDialog()}" />
<h:message for="ex" />
Remove the ViewScoped
Require a javax.faces.event.ActionEvent in the method
public void createDialog(ActionEvent event) {
System.out.println("%%%%%%%%%%%%%%%%%%%%%%%%%");
Change the method signature
action="#{myController.createDialog(5)}"
and
public void createDialog(int s) {
System.out.println("%%%%%%%%%%%%%%%%%%%%%%%%%");
I even tried to create a WEB-INF/faces-config.xml (which I would prefer not to, and according to PrimeFaces documentation I do not need it) with:
<?xml version='1.0' encoding='UTF-8'?>
<faces-config version="2.2"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd">
<application>
<action-listener>org.primefaces.application.DialogActionListener</action-listener>
<navigation-handler>org.primefaces.application.DialogNavigationHandler</navigation-handler>
<view-handler>org.primefaces.application.DialogViewHandler</view-handler>
</application>
<lifecycle>
<phase-listener>org.primefaces.component.lifecycle.LifecyclePhaseListener</phase-listener>
</lifecycle>
Other answers I have checked are: 1, 2, 3, 4, 5, 6
Apparently the use of actionListeners in PrimeFaces is not as correct as it should be... Is there another way to use PrimeFaces components?
This Dialog Framework code works for me:
index.xhtml
<p:commandButton id="openDialogButton" value="open dialog" action="#{myBean.openDialog('origin')}">
<!-- dialogReturn event: data could be passed, see page 587 in PF 6.1 manual. -->
<p:ajax event="dialogReturn" listener="#{myBean.doSthOnDialogReturn}"/>
</p:commandButton>
myDialogPage.xhtml
<p:commandButton id="closeButtonDialog" value="close dialog"
action="#{myBean.closeDialog('false')}"/>
<p:commandButton id="closeButtonDialog2" value="close dialog 2"
action="#{myBean.closeDialog('true')}"
ajax="false" validateClient="true"/>
Note: Example shows how to pass parameter from dialog. You can also notice, that the first button does just return while the second one does validation at first. I think these things can be useful.
myBean.java
public void openDialog(String origin) {
RequestContext.getCurrentInstance().openDialog("myDialogPage",
options, null);
}
public void closeDialog(Boolean param) {
RequestContext.getCurrentInstance().closeDialog(param);
}
public void doSthOnDialogReturn(SelectEvent event) {
if ((Boolean) event.getObject()) { // retrieve param value
doSth();
}
}
WEB-INF/faces-config.xml
<application>
<action-listener>
org.primefaces.application.DialogActionListener
</action-listener>
<navigation-handler>
org.primefaces.application.DialogNavigationHandler
</navigation-handler>
<view-handler>
org.primefaces.application.DialogViewHandler
</view-handler>
</application>
Finally I got to see some error:
SEVERE - /page.xhtml #159,146 actionListener="#{myController.createDialog()}": Target Unreachable, identifier 'myController' resolved to null
The trick to enable the display of error messages was to add the following in faces-config.xml:
<factory>
<exception-handler-factory>org.primefaces.application.exceptionhandler.PrimeExceptionHandlerFactory</exception-handler-factory>
</factory>
After checking this, I realised that my beans.xml file had been somehow deleted (??)

Primefaces Dialog Framework - Open dialog - close it - open another dialog

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

access variable in backing bean from jsf page

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.

Resources