This question already has answers here:
How to use Primefaces' p:growl and redirect to a page
(3 answers)
Closed 6 years ago.
I'm using primefaces 3.5 and I can't figure it out how to growl a message on the next page. For instance I want to add a record in database and after that I make a redirection to another page where I want to show a growl message with "The record has been added with success!"
I tried something like this:
public String addLabelInDB() {
try {
//logic to add a record in DB
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Success!", "Label has been added with success!"));
} catch (Exception e) {
logger.debug(e.getMessage());
}
return "listLabelsPage";
}
and in listLabelsPage.xhtml I have:
<p:growl id="msgs" showDetail="true" autoUpdate="true"/>
but it doesn't work.
I supposed the message is getting lost because is another request or something? It's there any possibility to store the message on request and show it on the next page? Thanks!
You can have a preRender set on the listLabelsPage.xhtml page you're loading
<f:event type="preRenderView" listener="#{yourBean.showGrowl}" />
and a showGrowl method having only
public void showGrowl() {
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Success!", "Label has been added with success!"));
}
I post an answer to my own question in order to help another people which face the same problem like I did:
public String addLabelInDB() {
try {
//some logic to insert in db
//below I set a flag on context which helps me to display a growl message only when the insertion was done with success
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
ec.getRequestMap().put("addedWithSuccess","true");
} catch (Exception e) {
logger.debug(e.getMessage());
}
return "listLabelsPage";
}
public void showGrowl() {
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
String labelAddedWithSuccess = (String) ec.getRequestMap().get("addedWithSuccess");
//if the flag on context is true show the growl message
if (labelAddedWithSuccess!=null && labelAddedWithSuccess.equals("true")) {
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Success!", "Label has been added with success!"));
}
}
and in my xhtml I have:
<f:event type="preRenderView" listener="#{labelsManager.showGrowl}" />
How about this? Make a separated redirect button which will be hit after showing msg:
HTML:
<h:form prependId="false">
<p:growl />
<p:button outcome="gotoABC" id="rdr-btn" style="display: none;" />
<p:commandButton action="#{bean.process()}" update="#form" />
</form>
Bean:
public void process(){
addInfoMsg(summary, msgDetail); //Add msg func
RequestContext.getCurrentInstance().execute("setTimeout(function(){ $('#rdr-btn').click(); }, 3000);"); // 3 seconds delay. I put the script in Constants to config later.
}
Related
This question already has answers here:
How can I add FacesMessage during page load? Using #PostConstruct does not seem to work
(3 answers)
Closed 4 years ago.
I can display an error/info message when a button is clicked using JSF, but I can't display a message when a page is loaded.
Please try the following.
index.xhtml:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:form id="componentForm">
<h:messages errorStyle="color: red" infoStyle="color: green" globalOnly="true" />
Enter the word Java here:
<h:inputText id="javaText" value="#{messageController.javaText}" />
<h:message for="javaText" errorStyle="color: red" infoStyle="color: green" />
<h:commandButton id="addMessage" action="#{messageController.newMessage}"
value="New Message" />
</h:form>
</h:body>
</html>
MessageController.java:
#Named(value = "messageController")
#SessionScoped
public class MessageController implements Serializable {
int hitCounter = 0;
private String javaText;
public MessageController() {
javaText = null;
FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_INFO, "Managed Bean Initialized", null);
FacesContext.getCurrentInstance().addMessage(null, facesMsg);
}
public void newMessage() {
String hitMessage = null;
hitCounter++;
if (hitCounter > 1) {
hitMessage = hitCounter + " times";
} else {
hitMessage = hitCounter + " time";
}
Date currDate = new Date();
FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_ERROR, "You've pressed that button " + hitMessage + "! The current date and time: " + currDate, null);
FacesContext.getCurrentInstance().addMessage(null, facesMsg);
if (getJavaText().equalsIgnoreCase("java")) {
FacesMessage javaTextMsg = new
FacesMessage(FacesMessage.SEVERITY_INFO, "Good Job, that is the correct text!", null);
FacesContext.getCurrentInstance()
.addMessage("componentForm:javaText", javaTextMsg);
} else {
FacesMessage javaTextMsg = new
FacesMessage(FacesMessage.SEVERITY_ERROR, "Sorry, that is NOT the correct text!", null);
FacesContext.getCurrentInstance()
.addMessage("componentForm:javaText", javaTextMsg);
}
}
public String getJavaText() {
return javaText;
}
public void setJavaText(String javaText) {
this.javaText = javaText;
}
}
Every message is displayed correctly except for one message that is created by a constructor.
I want to display the message Managed Bean Initialized when the page is loaded.
I Got the same issue, Unfortunately FacesContext only init when page loaded.
So you can not use FacesContext.getCurrentInstance().addMessage() when page is initializing :(
There are 2 solution that i tried
When document ready, call ajax to show message
Pass String message and display it
I've a command link:
<h:commandLink value="Delete"
onclick="return confirm('Are you sure?');"
action="#{bean.deleteDestination(destination, '/destination/show')}" />
It invokes this managed bean action method:
public String deleteDestination(Destination selected, String action) {
List<Flight> flights = getEjbFlightFacade().findFlightWithDestination(selected);
if (flights.isEmpty()) {
getEjbDestinationFacade().remove(selected);
setDestinations(getEjbDestinationFacade().findAll());
}
else {
// Here need to show an alert() that user can't remove the item.
}
return action;
}
As indicated by the comment, I'd like to show an alert() that the enduser can't remove the item. How can I achieve that?
Let JSF conditionally render the desired script based on a bean property.
E.g.
this.undeleteable = true;
<h:outputScript rendered="#{bean.undeleteable}">
alert("You can't delete it.");
</h:outputScript>
The canonical way, however, is to just show a (global) faces message.
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage("You can't delete it."));
<h:messages globalOnly="true" />
Alerts are namely soo 1990.
I'm trying to show a FacesMessage built in onFlowProcess of a primefaces wizard.
public String onFlowProcess(FlowEvent event) {
if (event.getOldStep().equalsIgnoreCase("otherTab")){
if (!hasImage){
FacesUtils.addMessage(null, "Error", "image is required", FacesMessage.SEVERITY_ERROR);
return event.getOldStep();
}
}
return event.getNewStep();
}
The message should be send to the growl but I believe that by invoking getOldStep(), the message is lost along the way.
My growl is declared as :
<p:growl life="2500" showDetail="true" globalOnly="true"/>
and the wizard contains flowListener="#{bean.onFlowProcess}".
I tried to keep my FacesMessage with
FacesContext.getCurrentInstance().getExternalContext().getFlash().setKeepMessages(true);
but this seems to work only for page redirect...
If anybody has any idea... Thx
I solved the problem by updating the <p:growl> from the bean:
RequestContext.getCurrentInstance().update("form:growl");
I have this JSF button which calls Java method when it's pressed:
<h:commandButton id="editdata" value="HiddenDelete" style="position:absolute; bottom:25px; right:650px;" actionListener="#{bean.saveData}" rendered="#{bean.editable}">
<f:ajax render="#form" execute="#form"></f:ajax>
</h:commandButton>
public void saveData() throws SQLException
{
.....
}
When I make a AJAX call the button is not working properly. Can you help me to find why the Java method is not called after AJAX call?
You're not passing the event:
public void saveData(AjaxBehaviorEvent event) { ... }
Also, what do you expect to happen with the Exception you're throwing? Shouldn't you catch it?
try {
// logic
}
catch(SQLException ex) {
FacesContext facesContext = FacesContext.getCurrentInstance();
FacesMessage facesMessage = new FacesMessage(
"There was an error, ....");
facesContext.addMessage(null, facesMessage);
}
This will be printed in HTML by <h:messages />.
I'm using PrimeFaces for a new project and it's quite an impressive set of components.
Anyway, I have problem with "real world" use of filedownload component.
In my page I have a datalist that shows the attachments related to a particular document, and I want provide a link to directly download that file inside the datalist item.
Here's my xhtml code:
<p:dataList id="ListaAllegati" value="#{documentBean.documento.allegati}" type="definition" var="attach" style="border: none" ">
<f:facet name="description">
<h:outputText value="#{attach.name}" />
<p:commandLink ajax="false" title="Download" action="#{documentBean.selectAttach}>
<h:graphicImage style="margin-left: 10px; border: none" value="./images/article.png" height="24" width="24" ></h:graphicImage>
<p:fileDownload value="#{documentBean.downloadFile}"/>
<f:setPropertyActionListener target="#{documentBean.selectedAttach}" value="#{attach}" />
</p:commandLink>
</f:facet>
</p:dataList>
and the relative java bean (request scoped):
private StreamedContent downloadFile;
public StreamedContent getDownloadFile() {
log.info("getter dell'allegato invocato");
InputStream stream = null;
byte[] rawFile = null;
if (selectedAttach == null) {
log.warn("Nessun allegato passato");
return null;
} else {
try {
log.info("Recupero del file " + selectedAttach.getGuid());
rawFile = attachManager.retrieveFile(selectedAttach.getGuid());
} catch (Exception e) {
String msg = "Errore durante il recupero del file";
log.error(msg, e);
FacesMessage fmsg = new FacesMessage(msg, "");
FacesContext.getCurrentInstance().addMessage(null, fmsg);
}
stream = new ByteArrayInputStream(rawFile);
DefaultStreamedContent file = new DefaultStreamedContent(stream,
selectedAttach.getMimeType(), selectedAttach.getName());
return file;
}
}
public void selectAttach() {
log.info("commandLink action invocata");
}
private Allegato selectedAttach;
public Allegato getSelectedAttach() {
return selectedAttach;
}
public void setSelectedAttach(Allegato selectedAttach) {
log.info("Allegato selezionato");
if (selectedAttach==null) log.warn("L'allegato passato รจ nullo");
this.selectedAttach = selectedAttach;
}
So, couple of question:
Am I doing the right thing trying to pass the selected attachment that way? Otherwise, how can I pass a parameter to tell the bean wich attachment has been clicked?
Why the first time I click the command link, nothing happen? It make a roundtrip with server, but nothing happens. Second time, it gives me an exception.
Why documentBean.selectAttach is never called and the documentBean.selectedAttach property is never set (neither the second time)?
Thanks to anyone for any hint
How to get the row object from the datatable is answered in this question:
How can I pass selected row to commandLink inside dataTable?
This answers basically all the three questions.
As to the exception in the second click, that's likely because you didn't return from the catch block when an exception is been thrown in your getDownloadFile() method. You're continuing the remnant of the code flow while the rawFile is still null. Fix it accordingly as well. Add a return null to the end of catch or something. Better yet, you should be posting the entire stacktrace in the question as you don't seem to be able to understand it. It basically already contains the answer :)
Primefaces has its own dedicated servlet for file download and upload components that handle all of this asynchronously.
Try doing something like what I have in my code
<p:commandLink ajax="false" actionListener="#{managedBean.downloadAction(object)}">
<span class="ui-icon icoFolderGo" style="padding-right: 1.5em;" />
<p:fileDownload value="#{managedBean.downloadContentProperty}" />
</p:commandLink>
And in the managed bean,
public void downloadAction(Object object) {
try {
InputStream stream = // get input stream from argument
this.setDownloadContentProperty(new DefaultStreamedContent(stream, "application/pdf", "filename.pdf");
} catch (Exception e) {
log.error(e);
}
}
public void setDownloadContentProperty(StreamedContent downloadContentProperty) {
this.downloadContentProperty = downloadContentProperty;
}
public StreamedContent getDownloadContentProperty() {
return downloadContentProperty;
}