How to make Primefaces Growl stack messages? - jsf

CommandButton displays the growl. But the previous growl message is lost. How can make growl display messages stack?
For example:
<h:form>
<p:growl id="growl" showDetail="true" life="6000" />
<p:commandButton value="Show" actionListener="#{growlView.showMessage}" update="growl" />
</h:form>
And bean function:
public void showMessage() {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Hello"));
}
I click button every second. I expect that messages will store and display for 6 seconds.
But after click button, previous message hides and i see only current message.
When i debugging i have that:
FacesContext.getCurrentInstance().getMessageList().size() == 0
I tried
FacesContext.getCurrentInstance().getExternalContext().getFlash().setKeepMessages(true);
than
<context-param>
<param-name>org.primefaces.messagePersistence</param-name>
<param-value>true</param-value>
</context-param>
But is doesn't work =(
Please help

An simple solution using the primefaces 5.1 for those who want to display messages on a stack manner in the same p:growl without hide the previous messages is to override the default behavior of the component adding a primefacesFixes.js file to the classpath and override the function with the commented line below:
primefacesFixes.js:
PrimeFaces.widget.Growl.prototype.show = function(b) {
var a = this;
this.jq.css("z-index", ++PrimeFaces.zindex);
//this.removeAll(); //Commenting this line prevents an ajax update tho the <p:growl> from erasing global messages
$.each(b, function(c, d) {
a.renderMessage(d);
});
};
So you call the fixes file like this on your template tag:
<h:outputScript name="javascript/primefacesFixes.js" target="head" />
And can use only one p:growl on the page to render all the needed messages.

Unfortunately, this is not currently possible. Actually, it was the default behaviour back in 2011 (having stacked growl messages) but the primefaces core team has decided to:
hide previous messages before displaying new ones on ajax update
Source: https://code.google.com/p/primefaces/issues/detail?id=1925
However, an issue was created here (October 2014) to bring back this feature but has not been reviewed yet.

Posting this on a old question, but this may be one solution (although, I'm on PFv6.2):
<p:growl id="messages" showDetail="true" keepAlive="true"/>
Simply add the keepAlive="true" to the growl element.

Related

Close dialog prior to navigate away from the page

PrimeFaces: 7.0
JSF: 2.2.13
JBoss: 7.1
Java: 1.8
Chrome: 83.0.4103.116
I have a simple confirmation dialog to go to another page, there a reason for the action should be provided as a text.
It boils down to the following lines of code:
<p:dialog id="dlg" widgetVar="dlg" modal="true">
<h:form id="dlgForm">
<p:inputText id="reason" required="true" value="#{bean.reason}"/>
<p:message for="reason"/>
<p:commandButton id="proceed" value="Proceed" update="dlgForm" action="#{bean.action}"/>
<p:commandButton id="cancel" value="Cancel" resetValues="true" onclick="PF('dlg').hide()">
<p:ajax update="dlgForm" resetValues="true"/>
</p:commandButton>
</h:form>
</p:dialog>
And the bean:
#ManagedBean(name = "bean")
#SessionScoped
class Bean {
public String processGrundFuerExportDlg() {
PrimeFaces.current().executeScript("PF('dlg').hide()");
return "other_page";
}
}
My requirements:
Dialog opens with the empty 'reason'-inputText.
If 'cancel' is pressed: dialog should close
If 'proceed' is pressed:
If reason is not empty: close dialog and navigate to the 'other_page'
If return is empty: show the error message and don't close the dialog
My problem with this code: the line
PrimeFaces.current().executeScript("PF('dlg').hide()");
seems to be executed AFTER the current page being left resulting in 'dlg' not being found (JavaScript error).
The not properly closed dialog produces a nasty side effect: After returning to my first page later on, the dialog overlay stays active and inputText elements can't be activated with the mouse (TAB works). Overlay logic in the event loop blocks mouse clicks to from being passed to the components on the page.
My question:
How this standard scenario should be properly implemented with JSF and PrimeFaces?
If Upgrade to other versions is required, are there some workaround for removing stale overlays without upgrading?
Disclaimer: I studied many related questions on StackOverflow and tried all proposed solutions without success. For example this one: Keep p:dialog open when a validation error occurs after submit
You won't be having this problem if you would redirect to the new page instead of triggering an Ajax update.
You can simply add ?faces-redirect=true to your returned string, so:
return "other_page?faces-redirect=true";
Or, if you are using faces-config, add <redirect/> to the <navigation-case>.
Then you can remove the script from your bean where you try to close the dialog.
See also:
How to navigate in JSF? How to make URL reflect current page (and not previous one)
If 'proceed' is pressed:
If reason is not empty: close dialog and navigate to the 'other_page'
If return is empty: show the error message and don't close the dialog.
All this above is handled with required true on reason inputText. If reason is empty action in proceed commandButton won't start.
You don' need to close your dialog before you are navigating to other page.

update outputtext from class

I have a RichFaces project on JSF 2.2 and I wanted to show status updates and messages to the user while processing their request. I wanted to use a a4j:outputpanel with a simple outputext for this. I added a system.out line and it shows up on my server console when but the text on the screen is not updated.
In my process class:
private void showAdvise(final String message) {
System.out.println(">>>>>ComUI showAdvise: " + message);
this.beidCardStatusBean.updateStatus(message);
}
On my jsf page:
- I launch the proces with:
<a style="font-size:150%;" onclick="startEID();"
href="savePhoto.do?userId=#{detailUserBean.id}">#{UIMessages['button.loadPhoto']}</a>
<a:outputPanel id="eidPaneContainer" ajaxRendered="true">
<rich:popupPanel header="EID" id="eidPane" width="100" height="80">
<h:outputText id="eidStatus" value="#{beidCardStatusBean.getStatus()}" >
</h:outputText>
</rich:popupPanel>
</a:outputPanel>
In order to update the components the page has to send a request to the server, it doesn't happen automatically when something on the server changes. The easy solution is to use a poll, e.g.
<a4j:poll id="poll" interval="2000" enabled="#{bean.pollEnabled}" render="poll, popup" />
This will rerender the popup every 2 seconds. So in your case startEID needs to set pollEnabled and rerender the poll to start it.
PopupPanel might be a bit problematic when it comes to rerendering, try setting domElementAttachment="parent" if this doesn't work.

Update JSF messages after initial rendering via p:menuitem

Does anyone know if it's possible to update a JSF message or messages element AFTER its initial rendering via PrimeFaces' p:menuitem?
For example, I have a PrimeFaces p:menuitem I am using to open a p:dialog, and that p:dialog has a p:messages element whose message I would like to update and show the moment that the p:dialog is opened - I can't know whether there is a message I want to show or what that message should be until after the p:menuitem's action method is complete.
Unfortunately, setting the update attribute of the p:menuitem to both the id of the p:dialog and the id of the p:messages element itself does not cause the p:messages element to show its message, even though I think it should since the action method of the p:menuitem looks like it is properly adding a message to the p:messages element.
The menuitem opening the dialog:
<p:menuitem value="Show Dialog with Message" action="#{myView.prepareDialogWithMessage()}" oncomplete="PF('dialogWidget').show()" update="dialogWithMessage message" />
The dialog with the message:
<p:dialog id="dialogWithMessage" widgetVar="dialogWidget" resizable="false" dynamic="true" closable="false" showEffect="fade" hideEffect="fade">
<p:messages id="message" for="message" showDetail="true" escape="false" autoUpdate="true"/>
<div class="button-panel">
<p:commandButton value="Yes" styleClass="ui-confirmdialog-yes" action="#{myView.submitAction()}" oncomplete="PF('dialogWidget').hide();"/>
<p:commandButton value="No" styleClass="ui-confirmdialog-no" onclick="PF('dialogWidget').hide();"/>
</div>
</p:dialog>
The Java code which adds the message:
public void prepareDialogWithMessage() {
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_WARN, "Summary of message we want to show when the dialog opens", "Details of the message we want to show when the dialog opens");
FacesContext.getCurrentInstance().addMessage("message", message);
}
Short answer: It behaves exactly as expected and implemented.
Longer answer:
Having a closer look after your edited question, I noticed the dynamic="true" on the dialog. If you read the PrimeFaces docs it states (as you already found out):
dynamic: Enables lazy loading of the content with ajax.
So when you show the dialog via javascript, its content is updated... Since this content also includes the p:messages, that is also updated. In your case updated again with the messages that are generated in the ajax call of the update of the dialog... Most likely none... So the messages you added to it in the prepareDialogWithMessage() call of the menuItem are lost.
Since you already update the dialog in the call to the menuItem, the dynamic='true' is totally superfluous and it throws a spanner in the works.
<off-topic>A suggestion is to always start creating an [mcve]. Removing more and more until the behaviour of certain parts is as expected. Removing the dynamic='true' in one of the steps would have resulted in this and you'd have known a lot more. At the same time, also try debugging more. Investigating by looking at the requests and responses in the browser developer tool. You would have seen the messages getting added to the dialog and then the dialog(contents) being totally overridden. All these things are easy too (sorry, easy instead of 'not to difficult), can/will tell you a lot and helps getting to the cause of things quicker. Either directly, or by being able to ask way more specific question that is often easier to answer</off-topic>

Primefaces fileupload ajax (growl)

i have the file upload using primefaces, in advanced mode,
<p:fileUpload fileUploadListener="#{fileUploadController.handleFileUpload(event)}"
mode="advanced"
update="messages"
sizeLimit="100000000"
allowTypes="/(\.|\/)(gif|jpe?g|png|doc|docx|txt|pdf)$/"
auto="true"/>
<p:growl id="messages" showDetail="true"/>
But i want to add a few nice finishing touches, like i have seen examples that use growl, that pops up a message saying success etc once completed, but am unsure on how to do this with glassfish, and do it on completion of the file being uploaded
Thanks
Solved the issue, my bean wasn't configured correctly thats all :)
EDIT :
Looked into the glassfish console and saw it was not calling the event caller, so it was skipping this enter section, i just simply changed the method call in the xhtml, and make sure the bean was correct, if anyone wants to see the bean just post a comment and ill add it :)

Primefaces editable dataTable and hibernate validator

I have an editable dataTable in PrimeFaces and am using the Hibernate Validator for bean validation. This works fine with a <p:inputText /> element. Now I want to have validation on a dataTable which is editable.
This is what is happening:
If I enter valid values, the page updates as expected
If I enter invalid values, when I click the little "save" check mark nothing happens - the cell remains editable, database write is not attempted, no error message is displayed.
There is an <h:messages /> tag on the page, so why doesn't an error message show up? The component appears to be aware there was a problem since the row remains in the editable state.
EDIT: I enabled logging and saw this:
21:20:43,874 FINE [javax.enterprise.resource.webcontainer.jsf.context] (http-localhost-127.0.0.1-8080-2) Adding Message[sourceId=demoTable:j_idt11:2:j_idt15,summary=Testing Hibernate Validator Error Message)
So it looks like the context is being correctly updated. It seems like I need to do something to trigger the message it render.
Use the belowfollowing statement in your jsf file and it should work:
<p:messages id="messages" showDetail="true" autoUpdate="true"
closable="true" showSummary="false"/>

Resources