Problem: For the below provided code snippet, the page reloads on click of h:commandButton if f:ajax onevent has function name provided as value, however for the same, if it has the function declaration provided as onevent value, it works as expected.
<?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 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:c="http://xmlns.jcp.org/jsp/jstl/core"" >
<h:head>
<h:outputStylesheet library="blue" name="style/style.css" />
<h:outputScript library="script" name="jquery-1.8.0.min.js" />
<script>
function jq(myid) {
return "#" + myid.replace( /(:|\.|\[|\]|,)/g, "\\\\$1" );
}
function confirmDelete(data){
if(data.status == "success") {
$("#confirmDelete").show();
$(jq("licenseForm:buttons")).hide();
}
return false;
}
</script>
</h:head>
<h:body styleClass="bodyForm">
<div class="content">
<h:form id="licenseForm">
<fieldset id="confirmDelete">
<h:panelGroup>
<h:panelGrid columns="2">
<h:selectOneMenu value="#{bean.deleteReason}">
<f:selectItems value="#{metadata.deleteReasons}" />
</h:selectOneMenu>
</h:panelGrid>
</h:panelGroup>
</fieldset>
<h:panelGroup id="buttons" layout="block">
<h:commandButton value="Delete" styleClass="button">
<f:ajax onevent="confirmDelete" />
</h:commandButton>
</h:panelGroup>
</h:form>
</div>
</h:body>
</html>
JSF Version: Mojarra JSF Implementation 2.2.12
Server: Apache Tomcat 8.0.24
This can happen if the webbrowser in question overrides the JavaScript function in some way. Internet Explorer and Chrome are known to put HTML elements with an id by their id in JavaScript global scope. So e.g. <element id="foo"> is available as variable foo in JavaScript global scope.
In your specific case, you have both a function confirmDelete() and a <fieldset id="confirmDelete">. It's however very unexpected that the DOM element would override the JavaScript function altogether. This suggests a bug in the browser used. Your best bet is to rename either the JavaScript function or the element ID to something unique in the global scope.
Unrelated to the concrete problem, your jq() is inefficient. This is better:
function jq(myid) {
return document.getElementById(myid);
}
You perhaps want to rename the function too. For other hints on using jQuery in JSF see also How to select JSF components using jQuery?
Related
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.
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>
I am having a problem here that seem to have the better of me.
Context
I have a p:dialog (primefaces) that show details of a JPA entity. From this dialog, the user can modify the information and submit it. Once submitted, the information is saved in DB (through JPA).
The p:dialog is "wrapped" in a Component for use in different situations.
Problem:
If I show the dialog with an entity selected from DB, modify some information and click on the save (submit) button: it works fine the first time. The DB is updated and p:dialog is hidden.
If I show again the dialog with the same entity, modify again a data from the p:dialog and submit again: everything seems to work fine (confirmation messages & logs) but the DB is not updated.
At all time, the information found in the p:dialog is right. The data found in the BackingBean & DB though, are up to date only after the first submit.
Another clue: if after a submit action I refresh the page, it will work for one more submit.
Debugging information:
According to the information Posted by the submit (long life to Firebug!!!) all the data posted are right (always up to date). But if I display in the log what the backing bean receives, it is the same content as the previous submit (and not the new information).
The data is posted correctly, but seems to be badly received/interpreted. It is just like if the problem was occurring at the reception of the submit's post, in one of the RestoreView, ApplyRequestValue, ProcessValidation or UpdateModelValue phases of the JSF life cycle.
So, the reason why the second save (submit) seems to work but doesn't is because the data saved in the DB is the same for every subsequent submit..... Why?
I use Glassfish 3.1.2, Mojarra 2.1.13, JSF, PrimeFaces, CDI, JPA, Hibernate...
Code Snipets:
page including the p:dialog (cmpnt:dataEntryDialog) as Component:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:cmpnt="http://java.sun.com/jsf/composite/component"
>
<h:head>
<title>
Test!!!
</title>
</h:head>
<h:body>
<h:commandButton type="button" onclick="PVDlg.show();" value="show dlg"/>
<cmpnt:dataEntryDialog id="PVDataEntry" video="#{processStatus.testedVideo}" fieldGroupId="2"
header="This is a test"
widgetVar="PVDlg" render="#this"/>
</h:body>
</html>
p:dialog's component implementation (cmpnt:dataEntryDialog):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:composite="http://java.sun.com/jsf/composite"
xmlns:c="http://java.sun.com/jsp/jstl/core"
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:p="http://primefaces.org/ui">
<composite:interface componentType="dataEntryComponent">
<composite:attribute name="video" required="true"/>
<composite:attribute name="widgetVar" required="true"/>
<composite:attribute name="render" required="false"/>
<composite:attribute name="closeActionListener" method-signature="void listener(org.primefaces.event.CloseEvent)" required="false" />
[... other attributes]
</composite:interface>
<composite:implementation>
<h:outputStylesheet library="css" name="dataEntryDialog.css" target="head" />
<div id="#{cc.clientId}">
<script type="text/javascript">
function handleDataEntrySaveAttempt(xhr, status, args) {
if( args.validationFailed || !args.saved ) {
jQuery('#' + #{cc.clientId} + ':cmpntDataEntryDialog').effect("shake", {times:3}, 100);
} else {
${cc.attrs.widgetVar}.hide();
}
return true;
}
</script>
<p:dialog
id="cmpntDataEntryDialog"
header="#{cc.attrs.header}"
widgetVar="#{cc.attrs.widgetVar}"
resizable="false"
showEffect="fade"
hideEffect="fade"
dynamic="true"
minimizable="true"
maximizable="false"
width="550"
height="500"
>
<h:form id="cmpntDataEntryForm" style="position:relative;">
<div style="height:460px;">
<div style="width:100%;height:100%;margin-bottom:5px;overflow:auto;">
<ui:repeat value="#{dataEntryDialog.loadDataEntryFields( cc.attrs.video, cc.attrs.fieldGroupId )}" var="field" varStatus="fieldRankInfo">
<div style="position:relative;width:100%;height:24px;margin:4px 0px;">
<h:outputText value="#{field.fieldName}:" style="vertical-align:middle;" styleClass="margin"/>
<p:calendar id="cmpntInputDate" value="#{field.value}" rendered="#{'java.util.Date' eq field.type}" styleClass="input margin" effect="drop" />
<p:selectOneMenu id="cmpntInputComboBox" value="#{field.value}" rendered="#{'ComboBox' eq field.type}" styleClass="input margin">
<f:selectItem itemLabel="SelectAValue"/>
<f:selectItems value="#{field.possibleValues}"/>
<f:converter converterId="com.ctec.world.ConvertInteger" />
</p:selectOneMenu>
[... some other optionally rendered fields for different data types]
</div>
</ui:repeat>
</div>
</div>
<div style="position:relative;bottom:0;">
<div style="float:right;margin-top:5px;">
<p:commandButton id="cmpntSubmit" action="#{dataEntryDialog.save( cc.attrs.video.video )}"
value="${cc.resourceBundleMap.dataEntryDialog_Save}"
process="#form" update="${cc.attrs.render} #form"
styleClass="margin" oncomplete="handleDataEntrySaveAttempt( xhr, status, args )"/>
<p:commandButton id="cmpntCancel"
value="${cc.resourceBundleMap.dataEntryDialog_Cancel}"
onclick="${cc.attrs.widgetVar}.hide();" styleClass="margin"/>
</div>
</div>
</h:form>
</p:dialog>
</div>
</composite:implementation>
</html>
Concerning the Managed beans, they are plain CDI #Named #SessionScoped bean.
ADDITIONAL INFORMATION:
I made further tests: went through phase listener to see if there is any object accessible from there having interesting information... no luck here until now.
I've got it! The problem is not on the presentation layer (what a surprise!). It is related on my logic. A little while ago, I have fixed an JPA Optimistic Lock Exception by changing entity instances (no longer managed by the entityManager) with the managed instance returned by the entity manager's merge method. My design wasn't supporting that change everywhere as expected... and I got lured by the post content which was right but not going in the entity instance I was expecting it to be. I guess more experience in web development won't hurt!
I'm having a problem with the tag in JSF2.0 and I hope someone can point out what I'm doing wrong. Here's what I've got in the UI:
<h:panelGroup>
<h:form id="theForm">
<h:selectOneMenu id="theMenu" value="#{viewBean.selectedItem}">
<f:ajax event="change" render="selectedItemText"/>
<f:selectItem itemLabel=""/>
<f:selectItems value="#{viewBean.selectableItems}"/>
</h:selectOneMenu>
<h:outputText id="selectedItemText" value="#{viewBean.selectedItemText}" />
</h:form>
</h:panelGroup>
This is working great - my conversation-scoped backing bean has a method setSelectedItem, and it's called and it does its thing the first time I select a different item from the menu; the output text is updated in the frontend, and I'm happy. However, further changes to the menu selection do not trigger a call to the setter via ajax. I've also tried this with a listener on the f:ajax tag - the listener method is only called that first time as well (breakpoints in the code to figure this out).
Am I doing something incorrectly?
I had a similar problem.
My second commandButton below only works once in the JSF view below that has a view param. Adding <f:param> to my first commandButton solved the problem. This is a situation not covered by BalusC's very helpful discussion.
<!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:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<f:view>
<f:metadata>
<f:viewParam name="id" value="#{fooManager.millis}" required="true"/>
</f:metadata>
<h:head>
<meta http-equiv="content-type" content="text/html;charset=utf-8"/>
</h:head>
<h:body>
<h:form id="fooForm">
<h:commandButton
id="barBbutton"
value="foo:test"
action="#{fooManager.test}">
<f:param name="id" value="1"/>
<f:ajax render="fooMillis1"/>
</h:commandButton>
<p>
<h:outputText id="fooMillis1" value="foo:display1: #{fooManager.millis}"/>
</p>
<p>
<h:outputText id="fooMillis2" value="foo:display2: #{fooManager.millis}"/>
</p>
</h:form>
<h:form id="barForm">
<h:commandButton
id="barButton"
value="bar:test"
action="#{barManager.test}">
<f:ajax render="barMillis1"/>
</h:commandButton>
<p>
<h:outputText id="barMillis1" value="bar:display1: #{barManager.millis}"/>
</p>
<p>
<h:outputText id="barMillis2" value="bar:display2: #{barManager.millis}"/>
</p>
</h:form>
</h:body>
</f:view>
</html>
And my FooManager and BarManager look the same:
#ManagedBean
#ViewScoped
public class FooManager {
public long getMillis() {
return millis;
}
public void setMillis(long millis) {
this.millis = millis;
}
public void test() {
setMillis(System.currentTimeMillis());
}
private long millis;
}
When it is not working, my Weblogic/Mojarra library does not give any helpful hint. There is no error anywhere. It was only after numerous tries that I came up with a working button like the first one above.
I had the same issue.
For the code below ajax was run only once.
<h:inputText id="element_id" value="#{viewBean.someValue}"></h:inputText>
<h:commandLink action="#{viewBean.someAction}" value="click me">
<f:ajax render=":my_form:another_element" execute="element_id> </f:ajax>
</h:commandLink>
When I add to render attribute the element which I'm executing then the ajax is triggered every time.
<h:inputText id="element_id" value="#{viewBean.someValue}"></h:inputText>
<h:commandLink action="#{viewBean.someAction}" value="click me">
<f:ajax render=":my_form:another_element element_id" execute="element_id> </f:ajax>
</h:commandLink>
I had a similar problem, in my case everithing worked fine in all browsers except that in IE9 the ajax was fired only once.
I was using render="#form" and when I changed it to render="#all", it worked fine. I dunno why, since I only have one Form in that page, and all my components are in that form.
So I would advise you to check the render and execute tags, at least in my case it was the solution
I had the same bug, fixed it using Primeface's p:ajax instead of f:ajax.