I display messages in my application
However, the messages are shown brifely and I would like to keep them on screen until they are closed manually.
How can i achieve this ?
EDITED:
I invoke the run method where messages are made.
I invoke the component pbAjax which then updates the growl element
I use
<p:growl id="growl" />
<p:commandButton value="Run" actionListener="#{myBean.run}" id="btnSubmitCreation" onclick="PF('pbAjax').start();"
<p:progressBar widgetVar="pbAjax" ajax="true" value="#{progressBean.progress}" styleClass="animated" >
<p:ajax event="complete" listener="#{controleBean.onComplete}" update="growl" oncomplete="startButton2.enable()"/>
</p:progressBar>
Java code:
public void run() {
...
...
List<String> messages = expResult.getMessages();
for (String message:messages){
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,message,message));
}
}
Just add sticky="true" in growl tag.
Related
I'm using jsf and Primefaces and I need some help.
I built in my project a IdleMonitor. It will trigger after the timeout a growl and I want to build in a clickable link. But my problem is that I can't add html code into the bean and didn't find anything about actions after clicking on the growl.
public void onActive() {
String link = "http://abcd.efg.com";
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_FATAL, "Deine Session ist abgelaufen", link));
}
xhtml:
<h:form>
<prime:growl id="messages" showDetail="true" sticky="true" redisplay="false" escape="false"/>
<prime:idleMonitor timeout="5000">
<prime:ajax event="idle" listener="#{idleMonitorView.onActive}" update="messages" />
<prime:ajax event="active" listener="#{idleMonitorView.onActive}" update="messages"/>
</prime:idleMonitor>
</h:form>
I need your help in showing an error message in the dialog. By clicking on the commandButton, no message is shown in the dialog.
Even though I tried to show the message in a dialog, but nothing is shown without any error.
So how can I produce messages in a dialog and not in the main form
Here is the JSF page code:
<h:form id="Requests">
<p:messages id="messages" showDetail="true" autoUpdate="true" closable="true"/>
<p:dialog id="c1" header="C1" widgetVar="c1">
<p:message id="messagePDFSTAR"
for=":Requests:DownloadPDFSTAR"
showDetail="true" />
<p:commandButton id="DownloadPDFSTAR"
value="Download"
ajax="false"
actionListener="#{hrd.PDFSTAR}"
update=":Requests:messagePDFSTAR" >
<p:fileDownload value="#{hrd.fileSTAR}" />
</p:commandButton>
</p:dialog>
</h:form>
Here is the java bean code:
public void PDFSTAR() {
try {
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, "Ref is Null", "Ref is Null");
RequestContext.getCurrentInstance().showMessageInDialog(message);
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_FATAL, "Fatal!", "System Error"));
} catch (Exception e) {
e.printStackTrace();
}
}
It's because you have ajax=false at the commandButton, so, the attribute update::Requests:messagePDFSTAR isn't going to work.
You can't combine ajax=false and update="...", update attribute is only for ajax actions.
I understand you need the ajax=false because the p:fileDownload works with that, but maybe you can try another way to display the message you want.
I deal with that situation once and use a workaround, in p:dialog you can use a p:messages and autoUpdate=true.
<h:form id="Requests">
<p:messages id="messages" showDetail="true" autoUpdate="true" closable="true"/>
<p:dialog id="c1" header="C1" widgetVar="c1">
<p:messages id="messagesPDFSTAR"
autoUpdate="true"
showDetail="true" />
<p:commandButton id="DownloadPDFSTAR"
value="Download"
ajax="false"
actionListener="#{hrd.PDFSTAR}" >
<p:fileDownload value="#{hrd.fileSTAR}" />
</p:commandButton>
</p:dialog>
</h:form>
I hope that will help you.
Edit:
RequestContext.getCurrentInstance().showMessageInDialog(message);
It shows the message in a new dialog, but i think it's not what you want. You want to show the message in the same dialog of the commandButton and the fileDownLoad.
Ajax and update not working correctly
To update components as p:growl or p:messages after a download, or even at the start just use a p:remoteCommand and the PrimeFaces.monitorDownload(start, stop); as in the example provided here PrimeFaces File Download example
here is how I'd do it:
<script type="text/javascript">
function start() {
PF('statusDialog').show();
//maybe some other blah blah..
updateMyMessages();
}
function stop() {
PF('statusDialog').hide();
//maybe some other blah blah..
updateMyMessages();
}
</script>
<div class="card">
<p:dialog modal="true" widgetVar="statusDialog" header="Status" draggable="false" closable="false"
resizable="false">
<i class="pi pi-spinner pi-spin" style="font-size:3rem"></i>
</p:dialog>
<h:form>
<p:messages id="messagesPDFSTAR"/>
<p:remoteCommand name="updateMyMessages" update="messagesPDFSTAR" action="#{hrd.PDFSTAR}"/>
<p:commandButton value="Download" ajax="false" onclick="PrimeFaces.monitorDownload(start, stop);"
icon="pi pi-arrow-down" styleClass="p-mr-2">
<p:fileDownload value="#{fileDownloadView.file}"/>
</p:commandButton>
</div>
Please note that I called the remote command twice so you get two updates to your messages, also this will execute your action #{hrd.PDFSTAR} twice, once on download start and the other on download finish, so modify as you see fit.
You can always upgrade to PrimeFaces 10+ and use ajax="true" (the default) on the download command button.
I'm newest with primefaces. What I'm trying to do is to fill a h:outputText, but i have to use p:poll because I make a request and I have to wait for response and it can take some time until I get the answer.
<h:form id="form1">
<p:poll widgetVar="headerPoll" interval="3" listener="#{bean.refreshHeader()}" update="form1" />
</h:form>
<h:form id="bodyForm">
<p:commandButton actionListener = "#{bean.loadBody}" ajax="false" value="load body" /> <br/><br/>
<h:outputText id="bodyText" escape="false" value="#{bean.body}" />
<p:poll widgetVar="bodyPoll" interval="3" listener="#{bean.refreshBody()}" update="bodyText" />
</h:form>
The associated bean:
public void refreshHeader()
{
if(header != null)
{
RequestContext reqCtx = RequestContext.getCurrentInstance();
reqCtx.execute("headerPoll.stop();");
}
}
public void refreshBody()
{
if(body != null)
{
RequestContext reqCtx = RequestContext.getCurrentInstance();
reqCtx.execute("bodyPoll.stop();");
}
}
The problem is at refreshHeader() function. When headerPoll.stop() get executed it stop the first and the second poll. I need to stop only one.
How can I stop only one of these polls ?
See you have set interval=3 in both the polling that's why both the functions get called parallely. Try running polling at different time. Hope it will work :)
I am using JSF,with #ManagedBean annotation and using Primefaces, and I got the following problem.
Why the "onerror" is not triggered? The exception just appears in my console.
login.xhtml
<p:commandButton
value="teste"
action="#{loginBean.methodTest()}"
ajax="true"
immediate="false"
onerror="confirmation.show()" />
<p:dialog
appendToBody="true"
header="Atencao"
widgetVar="confirmation"
showEffect="bounce">
...
</p:dialog>
MyBean
#ManagedBean(name = "loginBean")
#SessionScoped
public class LoginBean {
public void methodTest() throws Exception {
System.out.println("hi");
throw new Exception("Exception Test");
}
This is the expected behavior...
onerror : Client side callback to execute when ajax request fails.
in your case there is no failure in the ajax request at all , that fact that you are throwing exception got nothing to do with ajax failure
onerror is called when jsf doesn't catch your exception, http error or so. Exception != error.
read this thread for further details Ajax Engine: onerror doesn't work (might provide you with some tips...)
See the following detailed explanation about f:ajax onerror
the onerror attribute looks for an http error status code which you need to provide yourself.
In your first example
public void methodTest() {
ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
HttpServletResponse response = (HttpServletResponse) context.getResponse();
response.setStatus(500);
System.out.println("hi");
}
should work.
Thanks everybody,
I solved this problem with a not very good way (but it worked out !), but i think perhaps you can help me to improve this way. I would like to throw a Ajax error into my "catch", and the "onerror" (insted of oncomplete) recive it, and open the dialog.
Is there possibility ??
Example that worked out , with a poor way:
<p:panel id="PanelLogin" header="Login" >
<h:form id="FormLogin" >
<br/>
<h:panelGrid columns="2">
<h:outputLabel for="user" value="Usuario:" />
<p:inputText id="user" required="true" value=" " size="75" />
<h:outputLabel for="pin" value="Senha:" />
<p:password id="pin" required="true" value=" " size="55" />
</h:panelGrid>
<p:commandButton styleClass="botaoLogin" value="OK" action="#{loginBean.checkLogin()}" ajax="true" oncomplete="if (#{loginBean.dialog}) confirmation.show()" />
</h:form>
</p:panel>
<p:dialog id="atencaoDialog" resizable="false" appendToBody="true" header="Atencao" widgetVar="confirmation" height="85" width="300" showEffect="bounce">
<div align="center">
<p:messages id="outputTextAtencaoDialog" autoUpdate="true" redisplay="false" />
</div>
<div style="text-align: center;">
<p:commandButton id="okButtonAtencaoDialog" value="OK" onclick="confirmation.hide();" />
</div>
</p:dialog>
MyBean
#ManagedBean(name = "loginBean")
#SessionScoped
public class LoginBean implements Serializable {
private boolean dialog;
...
public String checarAutenticacao() {
...
try {
...
return "/templantes/telaAplicacao.xhtml";
} catch (Throwable e) {
this.dialog = true;
// try to throw Ajax error instead of this below ??
FacesContext.getCurrentInstance().addMessage(null,new FacesMessage(e.getMessage()));
return null;
}
}
I have a JSF view with a Primefaces data table and a command button insite it, as fallows:
<p:messages id="statusMessages" showDetail="true" />
<h:form id="listForm">
<p:panel header="Wellsite List">
<br />
<h:outputLabel value="Welcome, #{wellsiteController.loggedUser.login}" />
<br />
<br />
<p:dataTable id="dataTable" var="wellsite" value="#{wellsiteController.wellsiteDataTableModel}"
paginator="true" rows="10" selection="#{wellsiteController.wellsite}">
<p:column selectionMode="single" style="width:18px" id="radioSelect" />
<p:column sortBy="#{wellsite.reference}" headerText="Wellsite ID">
<h:outputText value="#{wellsite.reference}" />
</p:column>
<p:column headerText="Allowed Groups">
<h:outputText value="#{wellsite.allowedGroups.toString()}" />
</p:column>
<f:facet name="footer">
<h:panelGrid columns="3">
<p:commandButton id="addWellsite" value="Add New Wellsite" icon="ui-icon-flag" ajax="false" action="#{wellsiteController.showAddWellsite}"/>
<p:commandButton id="editWellsite" value="Edit Selected Wellsite" icon="ui-icon-wrench" ajax="false" action="#{wellsiteController.showEditWellsite}"/>
<p:commandButton id="deleteWellsiteButton" value="Remove Selected Wellsite" icon="ui-icon-trash" onclick="confirmation.show()" type="button"/>
</h:panelGrid>
</f:facet>
</p:dataTable>
<p:spacer height="20" />
</p:panel>
<p:confirmDialog id="confirmDialog" message="Are you sure you want to remove the selected Wellsite along with all it's data?" header="Confirmation" severity="alert" widgetVar="confirmation">
<p:commandButton id="confirm" value="Yes" ajax="false" oncomplete="confirmation.hide()" action="#{wellsiteController.deleteWellsite}" />
<p:commandButton id="decline" value="Cancel" onclick="confirmation.hide()" type="button" />
</p:confirmDialog>
</h:form>
And here's the controller:
#ManagedBean(name = "wellsiteController")
#RequestScoped
public class WellsiteController implements Serializable {
private static final long serialVersionUID = 1L;
#ManagedProperty("#{wellsiteDao}")
private WellsiteDao wellsiteDao;
#ManagedProperty("#{userDao}")
private UserDao userDao;
#ManagedProperty("#{groupDao}")
private GroupDao groupDao;
#ManagedProperty("#{userController.loggedUser}")
private UserEnt loggedUser;
private WellsiteEnt wellsite;
private List<WellsiteEnt> wellsiteList;
DualListModel<GroupEnt> pickGroupsModel;
public WellsiteController(){
}
#PostConstruct
public void build(){
wellsite = new WellsiteEnt();
wellsite.setAllowedGroups(new ArrayList<GroupEnt>());
}
/*some getters & setters*/
public WellsiteDataTableModel getWellsiteDataTableModel(){
return new WellsiteDataTableModel(getWellsiteList());
}
public void setPickGroupsModel(DualListModel<GroupEnt> model){
pickGroupsModel = model;
}
public DualListModel<GroupEnt> getPickGroupsModel() {
if(pickGroupsModel == null){
List<GroupEnt> allGroups = groupDao.getAll();
List<GroupEnt> currentGroups = wellsite.getAllowedGroups();
for(GroupEnt g : currentGroups){
allGroups.remove(g);
}
pickGroupsModel = new DualListModel<GroupEnt>(allGroups, currentGroups);
}
return pickGroupsModel;
}
public String listWellsites(){
getWellsiteList();
return "listWellsites";
}
public String showAddWellsite(){
FacesContext context = FacesContext.getCurrentInstance();
setWellsite(new WellsiteEnt());
wellsite.setAllowedGroups(new ArrayList<GroupEnt>());
pickGroupsModel = null;
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,
"Fields annotated with a ' * ' are mandatory",""));
return "addWellsite";
}
public String addWellsite(){
FacesContext context = FacesContext.getCurrentInstance();
wellsite.setDate(new Date());
wellsite.setLastUpdate(wellsite.getDate());
try {
wellsiteDao.addWell(wellsite);
for(GroupEnt g : pickGroupsModel.getTarget()){
GroupEnt group = groupDao.getOne(g.getGroupId());
group.getGroupWellsites().add(wellsite);
groupDao.update(group);
}
return listWellsites();
} catch (Exception ex) {
Logger.getLogger(WellsiteController.class.getName()).log(Level.SEVERE, null, ex);
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,
ex.getMessage(),""));
return null;
}
}
}
This view gets rendered correctly. The datatable and buttons looks fine. The problem is that when first i click the "addWellsite" commandButton, nothing happens. The page just seems to refresh. If i click it again, as exception happens:
java.lang.NumberFormatException: For input string: "null"
Using a debugger, i found out that the "addWellsite"'s action is NOT called the first time, and so, not outcome is generated (thus, the page refresh).
The exception is probably comming from the lack of initialization in the current or the target views (since both view are displayed from action methods that were not called in the page refresh)
The question is: WHY the action method is not called the first time?
As from this answer:
Whenever an UICommand component fails to invoke the associated action, verify the following:
UICommand components must be placed inside an UIForm component (e.g. h:form).
I do have a h:form
You cannot nest multiple UIForm components in each other (watch out with include files!).
There's only one.
No validation/conversion error should have been occurred (use h:messages to get them all).
I have a h:messages that does not display any error.
If UICommand components are placed inside an UIData component, ensure that exactly the same DataModel (the object behind the UIData's value attribute) is preserved.
The commandButton is inside the dataTable, but the target view does not need the dataModel. As my controller code shows, the object is built as the view tries to retrive it. The next request is not using this dataTable, to i do not handle it anymore.
The rendered and disabled attributes of the component and all of the parent components should not evaluate to false during apply request values phase.
There's no rendered or disbled attributes.
Be sure that no PhaseListener or any EventListener in the request-response chain has changed the JSF lifecycle to skip the invoke action phase.
No phaseListener is defined.
Be sure that no Filter or Servlet in the same request-response chain has blocked the request fo the FacesServlet somehow.
No other Servlet is defined. I don't even know what a Filter is.
WHY the action method is not called the first time?
This can happen when a parent of this <h:form> was been rendered by an ajax request initiated by another <h:form> beforehand. The rendered/updated <h:form> would then lose its view state. This is caused by a bug in the JavaScript API as described in JSF issue 790 which is already fixed for the shortly upcoming JSF 2.2.
In the meanwhile, with JSF 2.0/2.1, you need to explicltly specify the client ID of the <h:form> in the render (or for PrimeFaces, the update) attribute of the action in the other form.
E.g.
<h:commandButton ...>
<f:ajax ... render=":listForm" />
</h:commandButton>
or
<p:commandButton ... update=":listForm" />
Or just make it a normal (non-ajax) request instead.
See also:
Communication in JSF 2 - Ajax rendering of content which contains another form