I have a problem with the h:messages tag in JSF that simply does not show any messages. In the Glassfish log are no errors when I click the button.
The setup is as follows:
test.xhtml:
<html 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:j="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>test</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</h:head>
<h:body>
<h:messages globalOnly="true"/>
<h:form id="loginform">
<p:commandButton id="testButton" value="Test"
action="#{loginSessionBean.test()}" />
</h:form>
</h:body>
</html>
With The SessionScopedBean:
#ManagedBean
#SessionScoped
public class LoginSessionBean implements Serializable {
private static final long serialVersionUID = 1L;
...
public String test(){
FacesContext fc = FacesContext.getCurrentInstance();
fc.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Test!", null));
return "";
}
You're sending an ajax request with PrimeFaces <p:commandButton>. Ajax requests have by default no form of feedback (unless PrimeFaces' autoUpdate="true" is been used somewhere). You should be explicitly specifying parts of the view which you'd like to update on ajax response.
One way is specifying the update attribute on <p:commandButton> to point to the client ID of the <h:messages> component.
<h:messages id="messages" ... />
<h:form>
<p:commandButton ... update=":messages" />
</h:form>
Another way is to replace it by PrimeFaces <p:messages> which has an autoUpdate attribute for the purpose of automatic update on ajax response.
<p:messages ... autoUpdate="true" />
<h:form>
<p:commandButton ... />
</h:form>
A completely different alternative is to turn off ajax by adding ajax="false" attribute to the button, this way a synchronous postback will be performed which effectively results in a full page update, exactly like as how the standard JSF <h:commandButton> behaves when used without <f:ajax>.
<h:messages ... />
<h:form>
<p:commandButton ... ajax="false" />
</h:form>
See also:
Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes
Related
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');
});
I have the below Test.xhtml where i can select mode as Sea/Air. I don't want to load the all the 4 pages(Page1.xhtml, Page2.xhtml, Page3.xhtml, Page4.xhtml) into the jsf view tree. In my scenario, mode once selected and saved that can not be changed to other mode. The saved mode will be shown as view mode. Since at any point of time i need only 2 files (Page1.xhtml, Page2.xhtml (or) Page3.xhtml, Page4.xhtml)... I am using the JSTL tag handler for dynamic including the pages. the below thing is working fine. But i am not able to understand how the rendering working.
Test.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<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:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:head><title>JSF And JSTL</title>
<link href="../css/styles.css"
rel="stylesheet" type="text/css"/>
</h:head>
<h:body>
<div align="center">
<h:form id="form1">
<h:panelGrid columns="2">
<h:outputLabel value="Select Mode"/>
<h:selectOneMenu id="selectPageId" value="#{testBean.selectedMode}">
<f:selectItem itemLabel="Select" />
<f:selectItem itemLabel="Sea" itemValue="sea" />
<f:selectItem itemLabel="Air" itemValue="air" />
<f:ajax execute="#this" render="pageGroup"/>
</h:selectOneMenu>
</h:panelGrid>
<h:panelGroup id="pageGroup">
<c:if test="#{'sea' eq testBean.selectedMode}">
<ui:include src="Page1.xhtml" />
<ui:include src="Page2.xhtml" />
</c:if>
<c:if test="#{'air' eq testBean.selectedMode}">
<ui:include src="Page3.xhtml" />
<ui:include src="Page4.xhtml" />
</c:if>
</h:panelGroup>
</h:form>
</div>
</h:body>
</html>
TestBean.java
package com.test;
#ManagedBean(name = "testBean")
#ViewScoped
public class TestBean {
private String selectedMode;
public String getSelectedMode() {
return selectedMode;
}
public void setSelectedMode(String selectedMode) {
this.selectedMode = selectedMode;
}
}
Updated Again
Please help to clarify the below.
When i send a request first time to access the Test.xhtml, the jsf view (UIViewRoot) gets created. Since testBean.selectedMode by default is null.. this created view would not contain any component details of <c:if> and <ui:include> which are inside of <h:panelGroup id="pageGroup">.
After that when i send a second request(ajax postback) by selecting the mode as sea, the UIViewRoot gets created again for the request in the Restore View Phase. While UIViewRoot creation for this request in Restore View Phase, the tag handlers(<c:xxx>, <f:xxx>, <ui:include>) will get executed.
Since the selected value 'sea' will be updated to model(TestBean.java) only in Update Model Values Phase, in the Restore View Phase the EL #{testBean.selectedMode} will be evaluated to null.
So in my example Test.xhtml page the both tag handlers (<c:if test="#{'sea' eq testBean.selectedMode}"> and <c:if test="#{'air' eq testBean.selectedMode}">) will be evaluated to false. So the UIViewRoot does not contain any information related to the components inside <h:panelGroup id="pageGroup">.
Even though the UIViewRoot does not contain the components information inside the <h:panelGroup id="pageGroup">, How JSF able to render the included pages(<ui:include src="Page1.xhtml" />,<ui:include src="Page2.xhtml" />) successfully?
I am not sure how JSF rendering happening here. While Rendering, Is JSF re-creating the component tree for the particular rendering part(<h:panelGroup id="pageGroup">).?
Note: The example is working fine when i select mode as sea/air. The corresponding parts are rendering correctly.
I have the below Test.xhtml where i can select mode as Sea/Air. I don't want to load the all the 4 pages(Page1.xhtml, Page2.xhtml, Page3.xhtml, Page4.xhtml) into the jsf view tree. In my scenario, mode once selected and saved that can not be changed to other mode. The saved mode will be shown as view mode. Since at any point of time i need only 2 files (Page1.xhtml, Page2.xhtml (or) Page3.xhtml, Page4.xhtml)... I am using the JSTL tag handler for dynamic including the pages. the below thing is working fine. But i am not able to understand how the rendering working.
Test.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<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:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:head><title>JSF And JSTL</title>
<link href="../css/styles.css"
rel="stylesheet" type="text/css"/>
</h:head>
<h:body>
<div align="center">
<h:form id="form1">
<h:panelGrid columns="2">
<h:outputLabel value="Select Mode"/>
<h:selectOneMenu id="selectPageId" value="#{testBean.selectedMode}">
<f:selectItem itemLabel="Select" />
<f:selectItem itemLabel="Sea" itemValue="sea" />
<f:selectItem itemLabel="Air" itemValue="air" />
<f:ajax execute="#this" render="pageGroup"/>
</h:selectOneMenu>
</h:panelGrid>
<h:panelGroup id="pageGroup">
<c:if test="#{'sea' eq testBean.selectedMode}">
<ui:include src="Page1.xhtml" />
<ui:include src="Page2.xhtml" />
</c:if>
<c:if test="#{'air' eq testBean.selectedMode}">
<ui:include src="Page3.xhtml" />
<ui:include src="Page4.xhtml" />
</c:if>
</h:panelGroup>
</h:form>
</div>
</h:body>
</html>
TestBean.java
package com.test;
#ManagedBean(name = "testBean")
#ViewScoped
public class TestBean {
private String selectedMode;
public String getSelectedMode() {
return selectedMode;
}
public void setSelectedMode(String selectedMode) {
this.selectedMode = selectedMode;
}
}
Updated Again
Please help to clarify the below.
When i send a request first time to access the Test.xhtml, the jsf view (UIViewRoot) gets created. Since testBean.selectedMode by default is null.. this created view would not contain any component details of <c:if> and <ui:include> which are inside of <h:panelGroup id="pageGroup">.
After that when i send a second request(ajax postback) by selecting the mode as sea, the UIViewRoot gets created again for the request in the Restore View Phase. While UIViewRoot creation for this request in Restore View Phase, the tag handlers(<c:xxx>, <f:xxx>, <ui:include>) will get executed.
Since the selected value 'sea' will be updated to model(TestBean.java) only in Update Model Values Phase, in the Restore View Phase the EL #{testBean.selectedMode} will be evaluated to null.
So in my example Test.xhtml page the both tag handlers (<c:if test="#{'sea' eq testBean.selectedMode}"> and <c:if test="#{'air' eq testBean.selectedMode}">) will be evaluated to false. So the UIViewRoot does not contain any information related to the components inside <h:panelGroup id="pageGroup">.
Even though the UIViewRoot does not contain the components information inside the <h:panelGroup id="pageGroup">, How JSF able to render the included pages(<ui:include src="Page1.xhtml" />,<ui:include src="Page2.xhtml" />) successfully?
I am not sure how JSF rendering happening here. While Rendering, Is JSF re-creating the component tree for the particular rendering part(<h:panelGroup id="pageGroup">).?
Note: The example is working fine when i select mode as sea/air. The corresponding parts are rendering correctly.
i want to pass GET parameter from URL to a method, that called by clicking on button.
For example i have URL: /someurl/semepage.xhtml?id=1. And i have a button on my page:
<p:commandButton value="say it" action="#{test.sayIt(param['id'])}"/>
The bean looks like:
#ManagedBean
#ViewScoped
public class Test{
public void sayIt(String value){
System.out.println(value);
}
}
But when i am clicking on button, its just not react. Why is this happen ? Method even not called.
If i pass arguments staticaly like here:
<p:commandButton value="say it" action="#{test.sayIt('someword')}"/>
everything is ok.
Here is one way - using the <f:param, like this:
<h:commandButton value="Test The Magic Word" action="#{test.sayIt}">
<f:param name="id" value="#{param['id']}"></f:param>
<f:ajax execute="something" render="something_else"></f:ajax>
</h:commandButton>
And in your bean
HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext()
.getRequest();
String id = request.getParameter("id");
#Daniel's response is OK, but here it goes a simpler JSF 2-ish alternative for your case, using <f:viewParam /> and EL parameter passing. Note the <f:ajax /> is not needed in this case, as <p:commandButton /> has ajax behaviour by default.
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head />
<h:body>
<f:metadata>
<f:viewParam name="id" />
</f:metadata>
<h:form>
<p:commandButton value="say it" action="#{bean.sayIt(id)}" />
</h:form>
</h:body>
</html>
#ManagedBean
#ViewScoped
public class Bean implements Serializable {
public void sayIt(String value) {
System.out.println(value);
}
}
Tested with JSF 2.2.5 and Primefaces 4. Remember changing tag namespaces in case of using JSF 2.1.x.
Just for the fun of it, have you tried request.getParameter('id')?
This question already has answers here:
commandButton/commandLink/ajax action/listener method not invoked or input value not set/updated
(12 answers)
Closed 6 years ago.
I have a page that has a preRender call that prepares everything to be displayed in the page. I'm not sure if it's relevant, but the page recieves a few params from the index.xhtml that precedes the experience.
I have a commandButton that I need to execute a server-side method (an update, to be precise). There is no need for a refresh on the page.
So I'm using ajax. Here's the button's, code
<h:commandButton value="Save">
<f:ajax event="click" listener="#{bean.save}"/>
</h:commandButton>
So far, on the java side, here's the bean's save method
public void save(){
log.debug("Save executed!");
}
I've added some logging to check what's being executed. When I click the button, the only thing that happens is that the preRender method is executed (and not entirely, just a part of it). Nothing else happens. Visually, the page is not refreshed or anything.
I suspect that when I click the button, the page is being refreshed and therefore, the preRender method (called Build()) is executed, but since there are no parameters (remember that the Build requires parameters passed through <f:param>), something bugs out.
Bottom line: I just need to execute the save method when clicking on the button without refreshing or redirecting anything.
Ideas?
--EDIT--
INDEX.XHTML
<html 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:c="http://java.sun.com/jstl/core">
<ui:define name="body">
<h:link outcome="agreementDetail.xhtml" value="EA-15558">
<f:param name="serviceId" value="EA-15558" />
<f:param name="site" value="NIC" />
</h:link>
</ui:define>
</html>
AgreementDetail.XHTML
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html 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:c="http://java.sun.com/jstl/core">
<f:view>
<f:event type="preRenderView" listener="#{agreement.build}"/>
</f:view>
<ui:define name="body">
<f:view>
<h:form>
<h:commandButton value="Save" action="#{agreement.save}">
<f:ajax/>
</h:commandButton><br/><br/>
<h:dataTable value="#{agreement.licenseServerNames}" var="licenseServerName">
<h:column>
<h:inputText value="#{licenseServerName}"/>
</h:column>
</h:dataTable>
</h:form>
</f:view>
</ui:define>
</html>
AgreementBean.java
#ManagedBean(name="agreement")
#RequestScoped
public class AgreementBean {
#ManagedProperty("#{param.serviceId}")
private String serviceId;
#ManagedProperty("#{param.site}")
private String site;
private List<String> licenseServerNames; //GETTERS AND SETTERS OMITTED TO AVOID EXCESS CODE
#PostConstruct
public void build(){
logger.debug("START");
methodOne();
logger.debug("END");
}
public void save(){
logger.debug("SAVE!!!!!");
for(String name : licenseServerNames){
logger.debug("Servername = "+name);
}
}
}
This worked for me."Show" is a boolean that you can set upon successful save.
<h:commandButton id="ajax" value="Save" action="{agreement.save}" >
<f:ajax execute="#form" render="#form" />
</h:commandButton>
<h:outputScript rendered="#{agreement.show}">alert("save");</h:outputScript>