Growl is not show me after delete - jsf

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);
}
}

Related

Update bean property while using actionListener [duplicate]

This question already has answers here:
p:commandbutton action doesn't work inside p:dialog
(4 answers)
Closed 2 years ago.
I have a dialog in a form. The dialog has an inputTextarea and a commandButton. The commandButton uses actionListener to call a method on the bean. My issue is that the data in the inputTextarea is not available to my actionListener's method. The comments field shown below is null on the bean. How can I get access to it's contents in my bean's method?
The Page:
<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:c="http://java.sun.com/jsp/jstl/core"
xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:p="http://primefaces.org/ui"
template="/common/template.xhtml">
<ui:define name="title">test</ui:define>
<ui:define name="head">
<h:outputStylesheet name="web0020.css" library="css"/>
</ui:define>
<ui:define name="content">
<p:panel id="fileUploads" header="File Uploads" style="margin-bottom:20px">
<h:form id="form">
<p:messages id="messages" showDetail="false" closable="true">
<p:autoUpdate/>
</p:messages>
<p:dialog header="Approve" widgetVar="approveDlg" modal="true" appendTo="#(body)">
<p:panelGrid columns="1" layout="grid" styleClass="ui-noborder">
<h:outputText value="Approve Submission" style="font-weight:bold;font-size:1.3em"/>
<p:outputLabel for="comments" value="Comments:" style="font-weight:bold"/>
<p:inputTextarea id="comments" value="#{testView.comments}"
rows="1" cols="100"/>
<p:commandButton value="Save"
actionListener="#{testView.approve()}"
icon="ui-icon-check" update=":form:messages"/>
</p:panelGrid>
</p:dialog>
<p:commandButton value="Approve" onclick="PF('approveDlg').show();" icon="fa fa-thumbs-up"
update=":form:messages"/>
</h:form>
</p:panel>
</ui:define>
</ui:composition>
#Named
#ViewScoped
public class TestView implements Serializable{
#SuppressWarnings("compatibility:1287963775427900593")
private static final long serialVersionUID = 1L;
public TestView() {
super();
}
private String comments;
public void approve() {
try {
System.out.println("Comment:" + comments); //THIS IS EMPTY
} catch (Exception e) {
FacesContext.getCurrentInstance()
.addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error! " + e.getMessage(), e.getMessage()));
}
}
public void setComments(String comments) {
this.comments = comments;
}
public String getComments() {
return comments;
}
}
Answered with this - Primefaces dialog with modal=true not working properly. In order to make a modal form, you have to use appendTo="#(body)" and if you use appendTo, you will be outside the page's form, so you have to embed a separate form (outside of the main page's form) inside your dialog

growl is not displayed on the second mobile page

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');
});

RequestContext won't work

I am having trouble to update the view from the bean in the back using PrimeFaces's RequestContext. In the example below I have a button and 2 panels. When pressing the button, I want to update one panel, but not the other one.
It does not work though and I can't find the error! requestContext.update("panela"); is fired, but doesn't do its job!
Help greatly appreciated!
The XHTML file:
<!DOCTYPE html>
<html xmlns="http://www.w3c.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head/>
<h:body>
<h:form>
<p:panelGrid columns="1">
<p:commandButton value="Save" actionListener="#{runtimeUpdatesBean.save}" />
<p:panel id="panela">
<h:outputText value="#{runtimeUpdatesBean.texta}"/>
</p:panel>
<p:panel id="panelb">
<h:outputText value="#{runtimeUpdatesBean.textb}"/>
</p:panel>
</p:panelGrid>
</h:form>
</h:body>
</html>
The bean:
package com.glasses.primework;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import org.primefaces.context.RequestContext;
#ManagedBean
#SessionScoped
public class RuntimeUpdatesBean {
private String texta;
private String textb;
private boolean outcome;
public String getTexta() {
texta += "a";
System.out.println("RuntimeUpdatesBean.getTexta() = " + texta);
return texta;
}
public String getTextb() {
textb += "b";
System.out.println("RuntimeUpdatesBean.getTextb() = " + textb);
return textb;
}
public void save() {
RequestContext requestContext = RequestContext.getCurrentInstance();
if(outcome) {
System.out.println("RuntimeUpdatesBean.save() = update panela");
requestContext.update("panela");
outcome = false;
} else {
System.out.println("RuntimeUpdatesBean.save() = update panelb");
requestContext.update("panelb");
outcome = true;
}
}
}
Well the problem is the ID of the component that you are referring.
In JSF when you place a component inside h:form (or Some Primefaces components like TabView), that component's Id will be generated based on the h:form id too.
Here is the Example:
<h:form id="panelaForm">
<p:panel id="panela">
....
</p:panel>
</h:form>
In the above case your p:panel's id will be generated as panelaForm:panela.
In your case since you haven't provided any ID for h:form a dynamic id will be attached like for example j_xyz:panela(you can see it using you browser's Inspect Element).
So If you wan to access p:panel with Id panela inside the same h:form then no need to attach the form Id.
But If you want to access the p:panel outside h:form then you need to attach the h:form id to access it.
Solution to you problem is: use an custom ID to your h:form (which is a best practice by the way..) and access the p:panel by attaching that form ID.
<h:form id="panelaForm">
<p:panel id="panela">
....
</p:panel>
</h:form>
And in Managed bean use:
RequestContext.getCurrentInstance().update("panelaForm:panela");
I'm the new guy here (Java EE) however below solution works for me:
<!DOCTYPE html>
<html xmlns="http://www.w3c.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head/>
<h:body>
<h:form id="form">
<p:panelGrid columns="1">
<p:commandButton value="Save" actionListener="#{runtimeUpdatesBean.save}" update=":form" />
<p:panel id="panela">
<h:outputText value="#{runtimeUpdatesBean.texta}"/>
</p:panel>
<p:panel id="panelb">
<h:outputText value="#{runtimeUpdatesBean.textb}"/>
</p:panel>
</p:panelGrid>
</h:form>
</h:body>

Using <f:view> on the template page in JSF

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.

Access and refresh dataTable after getting data

I have got some problems with my JSF page, and (probably) with backing bean. I have got own template and I fill the content area with some pages. I have got search page with commandbutton and I would like to get data from database (JPA) and than fill the datatable.
Look at my searchpeople.xhtml:
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
template="template.xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core">
<ui:define name="content">
<h:form id="sampleform">
<p:accordionPanel activeIndex="-1" id="accordingpanle">
<p:tab title="User options" >
<p:growl id="growl" showDetail="true" showSummary="true"/>
<p:commandButton id="searchbutton" action="#{mb_person.search}" value="Szukaj" update="personsearchresulttable" />
</p:tab>
</p:accordionPanel>
<p:dataTable id="personsearchresulttable" var="person" value="#{mb_person.people}" widgetVar="personTable" style="margin-top: 10px" >
<p:column headerText="Id" style="width:10%">
<h:outputText value="#{person.id}" />
</p:column>
<p:column headerText="Name" style="width:20%">
<h:outputText value="#{person.name}" />
</p:column>
<p:column headerText="Surname" style="width:20%">
<h:outputText value="#{person.surname}" />
</p:column>
<p:column headerText="Company">
<h:outputText value="#{person.companyName}" />
</p:column>
<p:column style="width:4%" headerText="Open">
<h:link outcome="persondetails" value="Open">
<!--<f:param name="personid" value="#{person.id}"/>-->
<f:param name="personid" value="10076"/>
</h:link>
</p:column>
</p:dataTable>
</h:form>
</ui:define>
</ui:composition>
And my backingbean with EJB injection.
#ManagedBean(name="mb_person")
public class MB_Person implements Serializable{
#EJB
private PersonFacade personFacade;
private List<PersonAndCompany> people = new ArrayList<PersonAndCompany>();
public MB_Person() {
}
public List<PersonAndCompany> getPeople() {
return people;
}
public void setPeople(List<PersonAndCompany> people) {
this.people = people;
}
public void search() {
int[] range = {0,5};
setPeople(personFacade.findPersonWithMoreThanXProjects(20));
setPeople(personFacade.findPersonAndCompanyName(range));
for(PersonAndCompany p:people){
System.out.println(p.getName());
}
}
public String goToPersonDatailPage(int id){
return "persondetails.jsf?personid="+id;
}
}
I tried small test and printout all data in method search and I received good results.
Someone can help me how to update dataTable using ajax? In this form I have got an exception
Cannot find component with identifier "personsearchresulttable" referenced from "sampleform:accordingpanle:searchbutton".
Relative client IDs are searched relative to parent NamingContainer component. The <p:accordionPanel> is by itself a NamingContainer. So the relative client ID personsearchresulttable would be searched inside the context of the <p:accordionPanel>. However, it's actually outside the panel, inside the <h:form>.
You need to change the relative client ID to be an absolute client ID.
update=":sampleform:personsearchresulttable"
See also:
How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"

Resources