On a single xhtml, I have two pages (p:page). Each page has a form and in each form, there is a growl defined. When I am on the first page, the growl is displayed upon clicking the button. However, when I am on the second page, the growl is not displayed. Below is the reproducible sample code.
The reason, why I did not use the update="#form", is that there is another form in an overlay panel and via #(.errorHandlingPanel) selector, I should be able to easily trigger the growl without knowing which page currently I'm on.
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui"
xmlns:pm="http://primefaces.org/mobile"
xmlns:ui="http://java.sun.com/jsf/facelets">
<f:view renderKitId="PRIMEFACES_MOBILE"/>
<h:head>
</h:head>
<h:body>
<pm:page id="first">
<pm:header title="Page 1"></pm:header>
<pm:content>
<h:form id="form1">
<ui:include src="error_handling.jspx"/>
<p:commandButton id="btn1" value="Save" actionListener="#{growlViewDev.saveMessage}"
update="#(.errorHandlingPanel)"
icon="check"/>
</h:form>
</pm:content>
<pm:footer>
<p:tabMenu>
<p:menuitem value="Page 1"
outcome="pm:first?transition=slide"/>
<p:menuitem value="Page 2"
outcome="pm:second?transition=slide"/>
</p:tabMenu>
</pm:footer>
</pm:page>
<pm:page id="second">
<pm:header title="Page 2"></pm:header>
<pm:content>
<h:form id="form2">
<ui:include src="error_handling.jspx"/>
<p:commandButton id="btn2" value="Save" actionListener="#{growlViewDev.saveMessage2}"
update="#(.errorHandlingPanel)"
icon="check"/>
</h:form>
</pm:content>
<pm:footer>
<p:tabMenu>
<p:menuitem value="Page 1"
outcome="pm:first?transition=slide"/>
<p:menuitem value="Page 2"
outcome="pm:second?transition=slide"/>
</p:tabMenu>
</pm:footer>
</pm:page>
</h:body>
</html>
-- error_handling.jspx
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
>
<ui:composition>
<p:outputPanel styleClass="errorHandlingPanel">
<p:growl showDetail="true" showSummary="true" escape="false" sticky="true" globalOnly="true"/>
</p:outputPanel>
</ui:composition>
</html>
-- managed bean
#ManagedBean
public class GrowlViewDev {
public void saveMessage() {
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage("Successful", "Your message: Button 1") );
context.addMessage(null, new FacesMessage("Second Message", "Additional Message Detail"));
}
public void saveMessage2() {
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage("Successful", "Your message: Button 2") );
context.addMessage(null, new FacesMessage("Second Message", "Additional Message Detail"));
}
}
Tested with 5.1, 5.2 and 5.3
Thanks, ilhami visne
Somehow it seems the show method is not invoked after page navigation. The only workaround i found out is manually showing the message in ajax component oncomplete attribute using following method:
<p:growl id="growl" widgetVar="growlWidgetVar"/>
<p:commandButton outcome="pm:otherPage" update=":growl" oncomplete="showGrowl('growlWidgetVar');"/>
/*
* show current growl message again - PF-mobile bug on page navigation not showing it
*
* #param widgetVar PF widgetVar
*/
function showGrowl(widgetVar)
{
PF(widgetVar).show(PF(widgetVar).cfg.msgs);
}
The navigation often takes even place if a growl shall be shown. For this case call it in the pageshow handler instead:
$(document).on('pageshow', '#myPage', function(){
showGrowl('growlWidgetVar');
});
Related
My purpose is to show an alert after a delete :
So my .xhmtl code is:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:p="http://primefaces.org/ui"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:h="http://xmlns.jcp.org/jsf/html">
<h:form id="form">
....
<p:growl autoUpdate="true" id="message" for="message" showDetail="true"/>
</h:form>
and in my bean after delete I do:
FacesMessage infoMsg = new FacesMessage(FacesMessage.SEVERITY_INFO, "DELETE", "DELETE OK" );
FacesContext.getCurrentInstance().addMessage("form:message", infoMsg);
The problem is the object is deleted correctly but the alert is not show. Anyone can help me?
Place growl component in own form like this.
<h:form id="growlForm">
<p:growl showDetail="true" life="8000" keepAlive="true"/>
</h:form>
And create a message like this
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Success!", "Deleted"));
PrimeFaces.current().ajax().update("growlForm");
Instead of using
PrimeFaces.current().ajax().update("growlForm");
You can also update the form by referencing it from the update attribute in your p:commandButton component. Also, your Bean which handels the request should not be RequestScoped, but ViewScoped.
In Primefaces 7 Documentation growl does not have autoupdate.
So you are using a different version.
I give you some sample code in case that you want to delete an item in a datatable
<h:form id="form">
<p:growl id="msgs1" showDetail="true" life="3000"/>
.....
<p:dataTable value="#{ManageBean.dataList}"
var="record"
widgetVar="rolesTable"
rowKey="#{record}">
<p:column headerText="Data" sortBy="#{record.desc }"
<h:outputText value="#{record.desc}"/>
</p:column>
<p:column headerText="Actions" width="100">
<p:commandLink
update="form" action="#{ManageBean.delete(record)}"
>
<h:graphicImage name="/icons/delete.png"
title="Delete"/>
</p:commandLink>
</p:dataTable>
And the code in ManageBean
public void delete(ObjectType object) {
//Your code for delete
db.dbTransactions.deleteObject(object);
//Create the message
FacesMessage msg = new FacesMessage("Successful Delete");
FacesContext.getCurrentInstance().addMessage(null, msg);
//Remove the object from your list
dataList.remove(object);
}
}
I have multiple pages, and on some, the FacesMessage appears, while on others they don't. But I can't figure out why. In my example below, ajax is at false, but on some ajax is at true like everywhere else, but not working even it's same code
In every case the method is called, log proves it, but the message did not show in some case
I have a menu bar, which is included on top of every page, as
<html xmlns="http://www.w3.org/1999/xhtml" xlmns:h="http://java.sun.com/jsf/html" xlmns:f="http://java.sun.com/jsf/core" xlmns:ui="http://java.sun.com/jsf/facelets" xlmns:p="http://primefaces.org/ui">
<f:view contentType="text/html">
<h:head>
<f:facet name="first">
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
<title>LOG</title>
</f:facet>
<h:body>
<p:growl showDetail="true" sticky="true">
<p:autoUpdate disabled="false" />
</p:growl>
...
<p:layout>
<p:layoutUnit position="center">
<ui:insert name="center" />
</p:layoutUnit>
</p:layout>
</h:body>
</f:view>
</html>
And working page is like
<!DOCTYPE HTML PUBLIC>
<ui:composition template="/menu.xhtml" xmlns="http://www.w3.org/1999/xhtml"
xlmns:h="http://java.sun.com/jsf/html" xlmns:f="http://java.sun.com/jsf/core"
xlmns:ui="http://java.sun.com/jsf/facelets" xlmns:p="http://primefaces.org/ui">
<ui:define name="center>
<h:form >
<p:commandButton action="#{firstBean.method()}" />
</h:form>
</ui:define>
</ui:composition>
Not working page is like (here ajax at false, but there is also non-working page with ajax true) :
<!DOCTYPE HTML PUBLIC>
<ui:composition template="/menu.xhtml" xmlns="http://www.w3.org/1999/xhtml"
xlmns:h="http://java.sun.com/jsf/html" xlmns:f="http://java.sun.com/jsf/core"
xlmns:ui="http://java.sun.com/jsf/facelets" xlmns:p="http://primefaces.org/ui">
<ui:define name="center>
<h:form enctype="mulipart/form-data" >
<h:inputFile value="#{secondBean.inputFile}" />
<p:commandButton ajax="false" action="#{secondBean.method()}" process="#form" />
</h:form>
</ui:define>
</ui:composition>
And both method() are 100% same :
public void method(){
new JSFUtils().sendMessage("Test 1");
Logger.getAnonymousLogger().severe("Test"); // Always worked, always called
//...
}
Where I have an util class
public calss JSFUtil{
public void sendMessage(String msg){
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(Faces.Message.SEVERITY_WARN, "Warn", msg));
}
}
I want to put this command Link on my view message so it gets rendered on the growl, and I can open a dialog when clicking that link.
<p:commandLink onclick="PF('dlg_new_user').show()" value="Click Here" />
<p:growl id="msgs" showDetail="true" sticky="true" globalOnly="true" escape="false" />
My message:
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Title" , message ));
I got it working using the solution below, but the content of the growl gets rendered with escaped html and it renders the link after some seconds.
String message = "User not found, Click Here to create new user";
For example:
WebPage
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>Test my Growl Message</title>
<link type="text/css" rel="stylesheet"
href="#{facesContext.externalContext.requestContextPath}/resources/css/controlpanel.css " />
</h:head>
<h:body>
<h:form id="test" prependId="false">
<p:growl id="msgs" showDetail="true" sticky="true" globalOnly="true" escape="false" />
<p:outputLabel>
No user found!! <p:commandButton id="btn" value="Click Here" action="#{searchMB.searchSPU}" styleClass="botao_form" update=":test, :msgs, :dialog_user" /> to new User.
</p:outputLabel>
</h:form>
<p:dialog id="dialog_user" header="New User" widgetVar="dlg_new_user"
position="center" draggable="true" resizable="false"
closeOnEscape="true" appendTo="#(body)" modal="true">
<!-- Dialog content -->
</p:dialog>
</h:body>
</html>
MB:
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
#ManagedBean(name="searchMB")
#SessionScoped
public class TesteMB {
private static final String mainMessage = "Username not founded.";
private static final String link = "CLCK HERE to create a new user.";
public String searchSPU(){
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "No register founded" , mainMessage + "<br/>" + link ));
return null;
}
}
Problem solved, I was using two growls and one of them was generating the wrong html code.
I have a DataTable (Primefaces 3.5, JSF 2.0) which is populated from a database. In the first column of this table, checkboxes are displayed (multiple row selection).
After selecting row(s), when a button (<p:commandButton>) is pressed, the selected rows are expected to be deleted from the database.
Before deleting row(s), a confirm message regarding the deletion of the selected row(s) is displayed in <p:confirmDialog> with two buttons Yes and No something like the following.
Test.xhtml:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition template="template/Template.xhtml"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<ui:define name="title">Test</ui:define>
<ui:define name="content">
<h:form id="form">
<p:dataTable id="dataTable" var="row" value="#{testManagedBean.list}"
selection="#{testManagedBean.selectedValues}"
rowKey="#{row.id}"
rowIndexVar="rowIndex">
<p:column selectionMode="multiple" style="width:5%; text-align: center;">
<f:facet name="footer">
----------------> <p:commandButton actionListener="#{testManagedBean.deleteMultipleActionListener}" oncomplete="confirmDeleteMultiple.show()" update=":form:confirmDialogDeleteMultiple" process=":form:dataTable" icon="ui-icon ui-icon-close"/>
</f:facet>
</p:column>
<p:column headerText="Index">
<h:outputText value="#{rowIndex+1}"/>
</p:column>
<p:column id="id" headerText="Id">
<h:outputText value="#{row.id}"/>
</p:column>
<p:column id="countryName" headerText="Description">
<h:outputText value="#{row.description}"/>
</p:column>
</p:dataTable>
---------------><p:confirmDialog id="confirmDialogDeleteMultiple" widgetVar="confirmDeleteMultiple" appendToBody="true" message="Delete row(s)?" showEffect="true" hideEffect="true" header="Deletion of row." severity="alert" closeOnEscape="true" closable="true">
<p:commandButton id="confirmDeleteMultiple" value="Yes" oncomplete="confirmDeleteMultiple.hide()" actionListener="#{testManagedBean.deleteMultiple}" process="#this dataTable" update="dataTable"/>
<p:commandButton id="declineDeleteMultiple" value="No" onclick="confirmDeleteMultiple.hide()" type="button" />
</p:confirmDialog>
</h:form>
</ui:define>
</ui:composition>
The managed bean:
#ManagedBean
#ViewScoped
public final class TestManagedBean implements Serializable
{
#EJB(mappedName="ejb/JNDI")
private TestService testService;
private List<Test> list;
private List<Test>selectedValues;
public TestManagedBean(){}
#PostConstruct
public void init()
{
list=testService.getList();
}
public List<Test> getList() {
return list;
}
public List<Test> getSelectedValues() {
return selectedValues;
}
public void setSelectedValues(List<Test> selectedValues) {
this.selectedValues = selectedValues;
}
public void deleteMultipleActionListener(ActionEvent actionEvent)
{
//Just show a warning message, when the delete button is pressed.
for(Test test:selectedValues)
{
System.out.println(test.getId()+" : "+test.getDescription());
}//Displays the list.
}
public void deleteMultiple(ActionEvent actionEvent)
{
System.out.println("multiple");
for(Test test:selectedValues)
{
System.out.println(test.getId()+" : "+test.getDescription());
}//The list is not null and empty.
}
}
When the button (indicated by an arrow in XHTML) is pressed, the deleteMultipleActionListener() method in the managed bean is invoked where it simply displays the list which is populated by the selected rows and the confirm dialog as shown in XHTML appears afterwards. (This is just to show a warning message before deletion. The loop in this method is just for the demonstration).
When the Yes button on the confirm dialog is pressed, the deleteMultiple() method is invoked which is responsible for actual deletion of rows (actionListioner in <p:commandButton> inside <p:confirmDialog>) and the deletion of rows should be performed but here the list of the selected rows retrieved here is empty (not null).
The resulting list inside the deleteMultiple() method is empty because of <f:view> on the template page. The template page is shown below.
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="#{localeBean.language}"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core">
--------->
<f:view locale="#{localeBean.locale}" encoding="UTF-8" contentType="text/html">
<f:loadBundle basename="messages.ResourceBundle" var="messages"/>
<h:head><title><ui:insert name="title">Default Title</ui:insert></title></h:head>
<h:body>
<p:layout fullPage="true">
<p:layoutUnit position="north" size="135" collapsed="false" resizable="false" closable="false" collapsible="false" gutter="6">
<h:form>
<h:selectOneMenu id="languages" value="#{localeBean.language}" onchange="submit();" style="position: absolute; right: 0; top: 50px;">
<f:selectItem itemValue="en" itemLabel="English" />
<f:selectItem itemValue="hi" itemLabel="Hindi" />
</h:selectOneMenu>
</h:form>
</p:layoutUnit>
<p:layoutUnit position="west" id="leftPanel" size="225" header="Menu Item" resizable="false" closable="false" collapsible="true" gutter="6">
</p:layoutUnit>
<p:layoutUnit position="center" size="2500" maxSize="2500">
<ui:insert name="content">Put default content here, if any.</ui:insert>
</p:layoutUnit>
</p:layout>
</h:body>
</f:view>
</html>
When I remove this template from the above Test.xhtml page and use this <f:view> tag on the Test.xhtml page itself, everything works fine and the list of the selected rows inside the deleteMultiple() method is obtained correctly.
So, what is going wrong? Why does the list become empty when the Yes button is pressed, if the template page is enclosed by <f:view>? Is it wrong? How to accomplish this? (<f:view> is used for the localization of the application as it can be imagined).
Your problem is solved when you replace the process="#this datatable" in your confirmDeleteMultiple by process="#this", which makes the button component only be processed. In fact you don't need Ajax to process your datatable when you send the deletion confirmation, because values for deletion are already stored in the bean since previous step (that's the main benefit of the view scope).
Making your datatable to be processed in your Ajax request invokes again the setSelectedValues setter, so the original value is getting overriden by the new (empty) selection.
I am not able to open Dialog from my Bean. I have also tried actionListener instead of action
This is how my JSF looks like:
<ui:composition template="../templates/site.xhtml"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:sec="http://www.springframework.org/security/tags">
<!-- remove me just for encoding check ä -->
<ui:define name="content">
<h:form id="form">
<h:panelGrid columns="1" cellpadding="5">
<p:commandButton value="Button" type="button" id="myButton"
action="#{testBean.showDialog}" />
</h:panelGrid>
</h:form>
<p:dialog id="testDialog" widgetVar="testDialog2"
header="My Test Dialog" modal="true" appendToBody="true">
<h:form>
<h:outputText value="Output" />
</h:form>
</p:dialog>
</ui:define>
And this is my Bean
#Component
#Scope("view")
public class TestBean {
public void showDialog(){
RequestContext.getCurrentInstance().execute("testDialog2.show()");
}
}
Your showDialog() method is not called at all. Remove type="button" as you want to use AJAX enable submit, not push button.