Every time I debug the application and type something in the Textbox, the Controller remember only when I refresh the page.
Without the ajax Tag it's working fine. So my guess: the rendering of the outputPanel does not Work. I set Breakpoints (ajax listener and field setter are both called) and tested it many times and the outcome was the controller only works when i clicked the button and then refreshed the page. Referring JSF, I work with Eclipse for Java EE and Tomcat v.9.0 and earlier.
Strange thing is that the execute attribute only has the id for the name input in its execute attribute and still the listener is called (sysout is printed), this is not to be expected accordimg to #9 in commandButton/commandLink/ajax action/listener method not invoked or input value not set/updated. But changing it to #form does not change it
new.xhtml:
<?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:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
>
<h:head>
</h:head>
<h:body>
<h:form id="formID">
<h:inputText id="name" value="#{LayoutController.name}"></h:inputText>
<h:commandButton value="Welcome Me">
<f:ajax event="click" listener="#{LayoutController.listen}" execute=":formID:name" render=":formID:output"/>
</h:commandButton>
<h:panelGroup id="output">
<h:outputText value="#{LayoutController.name}"/>
</h:panelGroup>
</h:form>
</h:body>
</html>
LayoutController.java:
package Template;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.event.AjaxBehaviorEvent;
#ManagedBean(name="LayoutController")
#SessionScoped
public class LayoutController{
private String name;
public LayoutController() {
this.name="";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void listen (AjaxBehaviorEvent event) {
this.name = this.name + " ! ";
System.out.println("Clicked");
}
}
Related
When I manually change the selected value of selectOneMenu:
selectOneMenu's selected value gets changed to '2'
I get '2' on the console which means that the 'selectOneMenuAjaxEvent' is WELL being invoked.
I get one XHR request on the Network tab of Firebug.
BUT when I try to change the selected value by clicking on the commandLink:
selectOneMenu's selected value gets changed to '2'
I get nothing in the editor console which means that the 'selectOneMenuAjaxEvent' is NOT being invoked.
I get also no any XHR requests on the Network tab of Firebug which means this ajax event even not being sent.
There is no any error shows up on the Firebug console.
Why is the selectOneMenu's ajax change event not being sent when the value changes by the commandLink?
index.xhtml
<?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://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head></h:head>
<h:body>
<h:form id="mainForm">
<h:selectOneMenu id="selectMenu" value="#{indexBean.selectedValue}">
<f:selectItem itemLabel="1" itemValue="1" />
<f:selectItem itemLabel="2" itemValue="2" />
<f:ajax listener="#{indexBean.selectOneMenuAjaxEvent}" />
</h:selectOneMenu>
<h:commandLink value="Change Selected Value"
action="#{indexBean.changeSelectedValue}"/>
</h:form>
</h:body>
</html>
IndexBean
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import java.io.Serializable;
#ManagedBean
#ViewScoped
public class IndexBean implements Serializable {
private String selectedValue = "1";
public void changeSelectedValue(){
selectedValue = "2";
}
public void selectOneMenuAjaxEvent(){
System.out.println(selectedValue);
}
public String getSelectedValue() {
return selectedValue;
}
public void setSelectedValue(String selectedValue) {
this.selectedValue = selectedValue;
}
}
I have a ViewScoped CDI bean (javax.faces.view.ViewScoped). It reconstructs (calls a #PostConstruct method) when an ajax render its parent element. What should I do?
Bean:
import javax.annotation.PostConstruct;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
#Named("test")
#ViewScoped
public class TestBean implements Serializable {
private List<Integer> items;
#PostConstruct
private void postConstruct() {
Logger.getLogger("asd").log(Level.INFO, "construct");
items = new ArrayList<Integer>();
items.add(0);
items.add(1);
items.add(3);
items.add(4);
items.add(7);
items.add(10);
}
public List<Integer> getItems() {
return items;
}
public void setItems(List<Integer> items) {
this.items = items;
}
}
View:
<?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:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:pt="http://xmlns.jcp.org/jsf/passthrough">
<h:head>
<title>Simple JSF Facelets page</title>
</h:head>
<h:body>
<h:form>
<h:commandButton value="No reconstructing">
<f:ajax render=":panel" />
</h:commandButton>
</h:form>
<h:panelGrid id="panel">
<h:panelGroup>
<h:form>
<h:commandButton value="Strange reconstructing occurs">
<f:ajax render=":panel" />
</h:commandButton>
</h:form>
<ui:repeat value="#{test.items}" var="i">
#{i}
</ui:repeat>
</h:panelGroup>
</h:panelGrid>
</h:body>
</html>
Firstly click on the first button.
I am using JSF 2.This is my controller.
package com.acc.validations;
import java.io.Serializable;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
#ManagedBean(name="user")
#SessionScoped
public class Controller implements Serializable{
private static final long serialVersionUID = 1L;
String name;
String password;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
private String checkUser(String name,String password) {
if(("admin".equalsIgnoreCase(name)) && ("admin".equalsIgnoreCase(password))){
return "result";
}else{
/*System.out.println("Enter Valid details");*/
FacesMessage msg = new FacesMessage("Authentication Failed.","Authentication Failed");
msg.setSeverity(FacesMessage.SEVERITY_ERROR);
return null;
}
}
public void execute(){
checkUser(name, password);
}
}
This is my XHTML Page.
<?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" >
<h:body>
<h1>Custom validator in JSF 2.0</h1>
<h:form >
<h:panelGrid columns="3">
User Name:
<h:inputText id="username" value="#{user.name}"
required="true" >
<f:validateLength minimum="4" maximum="15" />
</h:inputText>
<h:message for="username" style="color:red" />
Password :
<h:inputSecret id="password" value="#{user.password}"
required="true" >
<f:validator validatorId="com.acc.validations.PasswordValidator" />
</h:inputSecret>
</h:panelGrid>
<h:commandButton value="Submit" action="#{user.execute}" />
</h:form>
</h:body>
</html>
My Requirement is that if the user enters user name and password as "admin" the control should redirect to result.xhtml else it should display message in the facesContext that i had written in the contoller.
This is my result.xhtml
<?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">
<h:body>
<h1>Custom validator in JSF 2.0</h1>
<h:panelGrid columns="2">
Welcome to User :
<h:outputText value="#{user.name}" />
</h:panelGrid>
</h:body>
</html>
I am not able to render the result.xhtml eventhough i enter admin as username and password and also i am not getting any messages while i am entering wrong credentials.And also i am not getting any errors.Could u please help me in this regard in order to work as per my requirement.
Have you tried something like this :
In your .xhtml
<p:inputText id="j_username" required="true" value="#{login.nomLogin}" />
In your "controller"
#ManagedBean(name="login")
#SessionScoped
public class LoginBean implements Serializable {
private String nomLogin;
private Boolean isConnected = false;
//Getter and Setter for this one
public String checkValidUser(){
//To see the value of login
System.out.println("Login a pour valeur :"+ getNomLogin());
if((getNomLogin().equals("admin")== true){
isConnected =true;
return "ok";
}}}
This is how my login works, you can do the same thing with a boolean it depend of what you need.
I think you can test the value, if you have something like that :
you can potentially test the valor of this , for example my menu is hidden if anybody is connected and show if admin is connected :
<p:panel id="HidePanel" header="Menu caché" rendered="#{login.isConnected == 'true'}" />
Whatever I do, I can't make sense of the listener attribute of the f:ajax tag. The method won't get invoked. I don't get any error messages. Here's an example:
test.xhtml
<?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:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>
Example
</title>
</h:head>
<h:body>
<h:form>
<h:selectOneMenu value="#{testBean.value}">
<f:selectItem itemLabel="1" itemValue="1" />
<f:selectItem itemLabel="2" itemValue="2" />
<f:ajax render="messages" listener="#{testBean.processAjaxBehaviour}" onevent="test" />
</h:selectOneMenu>
<h:messages id="messages" />
</h:form>
<script type="text/javascript">
function test(event)
{
alert(event.status);
}
</script>
</h:body>
</html>
TestBean.java
package test;
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.AjaxBehaviorEvent;
import javax.faces.event.AbortProcessingException;
#ManagedBean
#ViewScoped
public class TestBean implements Serializable
{
int value = 2;
public int getValue()
{
return value;
}
public void setValue(int value)
{
value = value;
}
#PostConstruct
public void init()
{
System.out.println("Done constructing testBean.");
}
public void processAjaxBehaviour(AjaxBehaviorEvent event) throws AbortProcessingException
{
System.out.println("Processing AJAX behaviour.");
}
}
The function test is called three times, as expected, and I get the status "success". The listener processAjaxBehaviour isn't called however.
The init method is called. The second option element rendered by the f:selectItem gets selected as expected.
The page is generated correctly with appropriate values in managed bean, but ajax events in these two h:selectOneMenus don't works. Listener is not called. An error has to be somewhere within tags, but I don't see it.
<f:view>
<h:form>
<h:messages />
<h:panelGrid columns="3">
<h:outputLabel value="Choose your faculty: *" for="faculties" />
<h:selectOneMenu id="faculties" value="#{registrateStudent.selectedFaculty}" >
<f:ajax event="change" listener="#{registrateStudent.genSpecializations}" execute="faculties" render="specializations" />
<f:selectItems value="#{registrateStudent.listFaculty}" var="curFac" itemLabel="#{curFac.name}" itemValue="#{curFac}" />
</h:selectOneMenu>
<h:message id="message_faculties" for="faculties" />
<h:outputLabel value="Choose your specialization: *" for="specializations" />
<h:selectOneMenu id="specializations" value="#{registrateStudent.selectedSpecialization}" >
<f:selectItems value="#{registrateStudent.listSpecialization}" var="curSpec" itemLabel="#{curSpec.name}" itemValue="#{curSpec}"/>
</h:selectOneMenu>
<h:message id="message_specializations" for="specializations" />
Managed Bean:
#ManagedBean(name = "registrateStudent")
#ViewScoped
public class RegistrateStudent {
private Faculty selectedFaculty;
private List<Faculty> listFaculty;
private Specialization selectedSpecialization;
private List<Specialization> listSpecialization;
private boolean showSpecialization = false;
/** Creates a new instance of RegistrateStudent */
public RegistrateStudent() {
users = new Users();
System.out.println("poaposd1");
student = new Student();
}
#PostConstruct
public void init() {
listFaculty = ff.findAll();
if (listFaculty != null) {
selectedFaculty = listFaculty.get(0);
listSpecialization = sf.findByFaculty(selectedFaculty.getIdFaculty());
if (listSpecialization != null) {
selectedSpecialization = listSpecialization.get(0);
}
else {}
} else {}
}
public void genSpecializations(AjaxBehaviorEvent event) {
if (sf.findByFaculty(selectedFaculty.getIdFaculty()) != null) {
this.showSpecialization = true;
} else {
JsfUtil.addSuccessMessage("faculties", "We don't have specializations for such faculty");
}
}
}
UPDATE:
I've found out a few interesting things:
<f:ajax> tag doesn't work at <h:link>, <h:selectOneMenu>, <h:button>, <h:commandButton>. In this cases incorrect values in render attribute is not noticed, but incorrect value of event attribute generate an error.
<h:outputLabel>, <h:inputText> work with <f:ajax> properly
The <f:ajax> requires jsf.js file being included in the HTML <head>. It contains all JS functions for doing the JSF ajax magic.
To achieve this, ensure that you're using <h:head> instead of <head> in the master template. JSF will then automatically include the necessary <script> element there pointing to jsf.js.
<!DOCTYPE html>
<html lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title>Look, with h:head</title>
</h:head>
<h:body>
Put your content here.
</h:body>
</html>
Note that in a bit decent webbrowser with a bit decent webdeveloper toolset like Firefox's Web Developer Toolbar and/or Firebug you should immediately have noticed JS errors like jsf is undefined when the ajax request is to be executed. That should at least have given something to think about.
Update: as per your update
I've found out a few interesting things:
<f:ajax> tag doesn't work at <h:link>, <h:selectOneMenu>, <h:button>, <h:commandButton>. In this cases incorrect values in render attribute is not noticed, but incorrect value of event attribute generate an error.
<h:outputLabel>, <h:inputText> work with <f:ajax> properly.
The <h:link> and <h:button> are intented for GET requests only, not POST requests. It should however work just fine on <h:selectOneMenu> and <h:commandButton>. Don't you have more code into the complete picture which you omitted from the question for simplicity? Which JSF impl/version are you using? Are you using the right libraries in classpath? It look like that you must really have messed up something.
To convince you (and myself) I just created the following copy'n'paste'n'runnable testcase
<!DOCTYPE html>
<html lang="en"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
>
<h:head>
<title>SO question 6089924</title>
</h:head>
<h:body>
<h:form>
<h:selectOneMenu value="#{bean.selected}">
<f:selectItem itemValue="#{null}" itemLabel="Select..." />
<f:selectItem itemValue="one" />
<f:selectItem itemValue="two" />
<f:selectItem itemValue="three" />
<f:ajax listener="#{bean.listener}" render="result" />
</h:selectOneMenu>
<h:commandButton value="commandButton" action="#{bean.submit}">
<f:ajax listener="#{bean.listener}" render="result" />
</h:commandButton>
<h:outputText id="result" value="#{bean.selected} #{bean.result}" />
<h:messages />
</h:form>
</h:body>
</html>
with this bean
package com.example;
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.AjaxBehaviorEvent;
#ManagedBean
#ViewScoped
public class Bean implements Serializable {
private String selected;
private String result;
public void submit() {
System.out.println("submit");
}
public void listener(AjaxBehaviorEvent event) {
System.out.println("listener");
result = "called by " + event.getComponent().getClass().getName();
}
public String getSelected() {
return selected;
}
public void setSelected(String selected) {
this.selected = selected;
}
public String getResult() {
return result;
}
}
It runs fine with Mojarra 2.1.1 on Tomcat 7.0.12.
INFO: Starting Servlet Engine: Apache Tomcat/7.0.12
INFO: Initializing Mojarra 2.1.1 (FCS 20110408) for context '/playground'
Be careful if you have f:metadata and f:viewparam tags since the setters of the parameters will be called with every ajax request.
Can you provide the error log if there is any error/exception that is being generated when you call the ajax call?