JSF Ajax not rendering until a page refresh [duplicate] - jsf

This question already has an answer here:
Ajax update/render does not work on a component which has rendered attribute
(1 answer)
Closed 7 years ago.
Here is my view:
<?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:f="http://java.sun.com/jsf/core">
<h:head>
<title>Welcome</title>
</h:head>
<h:body>
<h:form prependId="false" id="myForm">
<h3>Please enter your name and password.</h3>
Name: <h:inputText id="name" value="#{user.name}"/>
Password: <h:inputSecret id="password" value="#{user.password}"/>
<h:commandButton value="Login">
<f:ajax execute="name password" render="greeting"/>
</h:commandButton>
<h:outputText id="greeting" value="Welcome + #{user.name}" rendered="#{user.nameRendered()}"/>
</h:form>
</h:body>
</html>
Any my User.java :
#Named
#SessionScoped
public class User implements Serializable {
private String name;
private 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;
}
public boolean nameRendered() {
return this.name != null;
}
}
So when I type something in Name field and click submit, I expect to see outputText with id"greeting" because, user.nameRendered() should return true.
However, I will need to refresh the page after I submit name to see it. Why might be the reason? Why does it require a page refresh? How can I do it without a page refresh?

You can't refresh components that are not rendered in the JSF tree, you need to encalsulate the output inside a component that will always exists :
<h:panelGroup id="greeting">
<h:outputText value="Welcome + #{user.name}" rendered="#{user.nameRendered()}"/>
</h:panelGroup>
More info :
Why do I need to nest a component with rendered some in another component

Related

primefaces commandButton not set input field value in ui:repeat

I have list in view scoped bean. The #{repeatController.add} a new object to the list. It call the h:commandButton and the p:commandButton also.
My problem is, when I have a new line, typing into the "repeatName" field something, after press h:commandButton or p:commandButton, they have different working.
The h:commandButton push the new field value to the bean and it appeared after refresh the form and the new line also.
The p:commandButton not push the new field value to the bean. After refresh the form the new line appeared, but the previously typed content of the "repeatName" field is empty.
I think the h:commandButton working fine, the p:commandButton is not working fine.
The "noRepeatName" field value always set with h:commandButton and p:commandButton.
Steps and result with h:commandButton:
push the button (create new line) more times.
type to the "noRepeatName" field
type to the the first "repeatName" field
push the button
Result: after refresh, previously typed content of the field appeared.
Steps and result with p:commandButton:
push the button (create new line) more times.
type to the "noRepeatName" field
type to the the first "repeatName" field
push the button
Result: after refresh, previously typed content of the "noRepeatName" field appeared, but the first "repeatName" is empty.
Do I miss something?
Why doesn't set the value of the first "repeatName" filed to the bean like with h:commandButton?
I use primefaces 6.2.10, jsf 2.2.18 (oracle) and spring boot 2.0.6.
JSF code
<?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:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head/>
<h:body>
<h:form id="repeatForm">
<h:commandButton value="plus" id="addJsf">
<f:ajax event="click" immediate="true" render="repeatForm" execute="repeatForm"
listener="#{repeatController.add}"/>
</h:commandButton>
<p:commandButton icon="fa fa-plus" actionListener="#{repeatController.add}" immediate="true" id="add"
process="repeatForm" update="repeatForm"/><br/>
<p:inputText value="#{repeatData.name}" id="noRepeatName">
<f:validateLength minimum="30"/>
</p:inputText><br/>
<ui:repeat value="#{repeatData.products}" var="product" varStatus="productStatus">
First: #{productStatus.first}"; Last: #{productStatus.last}; Index: #{productStatus.index}<br/>
<p:inputText value="#{product.name}" id="repeatName">
<f:validateLength minimum="20"/>
</p:inputText><br/>
</ui:repeat>
</h:form>
</h:body>
</html>
Java bean
#Named
#Scope("view)
public class RepeatData {
private List<Product> products = new ArrayList<>();
private String name;
public List<Product> getProducts() {
return products;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Product
public class Product {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Controller
#Named
#Scope("request")
public class RepeatController {
#Autowired
private RepeatData repeatData;
public void add() {
repeatData.getProducts().add(new Product());
}
}

h:selectBooleanCheckBox action on select

I have a <h:selectBooleanCheckBox> as part part of my JSF which I want to run a bean method when it's state has changed from unchecked to checked.
I have the following controller bean
#Named
#ViewScoped
public class UserController {
#Inject
private UserService userService;
#Inject
private LocationService locationService;
private UserFilter userFilter;
private List<User> users;
private List<Location> locations;
#PostConstruct
public void init() {
users = userService.listAll();
locations = locationService.listAll();
userFilter = new UserFilter();
}
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
public List<Location> getLocations() {
return locations;
}
public void setLocations(List<Location> locations) {
this.locations = locations;
}
public void listAllUsers() {
users = userService.listAll();
}
public void findUsers() {
// code that uses the UserFilter
// to decide which user filter find method to use
}
}
The UserFilter is a simple DTO
public class UserFilter {
private boolean allUsers = true;
private String username;
private String location;
//getters and setters
}
And my JSF has is like so
<?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>
<title>Users</title>
</h:head>
<h:body>
<h1>Users</h1>
<h:form id="filterForm">
<h:selectBooleanCheckbox id="selectAll" value="#{userController.userFilter.allUsers}" title="allUsers">
<f:ajax render="filterGrid"/>
</h:selectBooleanCheckbox><h:outputText value ="All users"/>
<h:panelGrid id="filterGrid" columns="3">
<h:inputText id="userName" value="#{userController.userFilter.userName}" disabled="#{userController.userFilter.allUsers}"/>
<h:selectOneMenu id="selectLocation" value="#{userController.userFilter.location}" disabled="#{userController.userFilter.allUsers}">
<f:selectItems value="#{userController.locations}" var="location" itemValue="#{location.location}" itemLabel="#{location.location}"/>
</h:selectOneMenu>
<h:commandButton value="Filter" disabled="#{userController.userFilter.allUsers}" action="#{userController.findUsers()}"/>
</h:panelGrid>
</h:form>
<h:form rendered="#{not empty userController.users}">
<h:dataTable value="#{userController.users}" var="user">
<h:column>#{user.name}</h:column>
<h:column>#{user.location.location}</h:column>
<h:column><h:commandButton value="delete" action="#{userController.delete(user)}"/></h:column>
</h:dataTable>
</h:form>
<h:panelGroup rendered="#{empty userController.users}">
<p>Table is empty! Please add new items.</p>
</h:panelGroup>
<h3>Add user</h3>
<h:form id="user">
<p>Value: <h:inputText id="name" /></p>
<p>
<h:commandButton value="add" action="#{userController.add(param['user:name'])}"/>
</p>
</h:form>
</h:body>
</html>
As you can see by default it lists all users, then when the checkbox is unchecked you have the option to filter on username/location.
What I want is for the check box to run the userController.listAllUsers() method when it's state moves from unchecked to checked.
And a small additional question, how do I get the checkbox to appear in the same row as the panel grid items?
I have a habit of answering my own questions it seems! I needed an additional <f:ajax tag that rendered the user form and had the listener attribute set
So something like
<h:selectBooleanCheckbox id="selectAll" value="#{userController.userFilter.allUsers}" title="allUsers">
<f:ajax render="filterGrid"/>
<f:ajax render="usersForm" listener="#{userController.listAllUsers()}"/>
</h:selectBooleanCheckbox><h:outputText value ="All users"/>

p:remoteCommand destroys #ViewScoped managed bean

I am having trouble adding a p:remoteCommand to a form. It looks something like:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"
xmlns:util="http://java.sun.com/jsf/composite/components/util"
xmlns:c="http://java.sun.com/jsp/jstl/core" xmlns:fn="http://java.sun.com/jsp/jstl/functions"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>Reset Test</title>
<link type="text/css" rel="stylesheet" href="/treetable-sscce/css/example.css" />
<h:outputScript library="primefaces" name="jquery/jquery.js"/>
</h:head>
<div class="box">
<h2>Box</h2>
<h:panelGroup id="mypanel">
Headline: <h:outputText value="#{resetBean.headline}" />
<br/>
Message : <h:outputText value="#{resetBean.message}" />
<br/>
</h:panelGroup>
</div>
<div class="box">
<h2>Form</h2>
<h:form id="myform" acceptcharset="utf-8">
<p:growl id="growl" showDetail="true" sticky="false" severity="info, warn" />
<!-- register custom validate event -->
<f:event listener="#{resetBean.validateForm}" type="postValidate" />
<p:remoteCommand name="resetByEscape" action="#{resetBean.resetAction}"
immediate="true" update=":myform :mypanel" />
<h:outputLabel for="headline">Meldungsüberschrift</h:outputLabel>
<h:inputText id="headline" value="#{resetBean.headline}" />
<br/>
<h:outputLabel for="message">Meldungsüberschrift</h:outputLabel>
<h:inputTextarea id="message" value="#{resetBean.message}" />
<br/>
<h:commandButton action="#{resetBean.resetAction}"
value="Reset" immediate="true" onclick="resetForm()"/>
<h:commandButton action="#{resetBean.submitAction}" value="Submit" immediate="false"/>
</h:form>
</div>
<script type="text/javascript">
<!--//--><![CDATA[//><!--
var resetForm = function()
{
$("[id$='headline']").val(null)
$("[id$='message']").val(null)
}
var escapePressed = function()
{
resetForm();
resetByEscape();
}
$(document).keyup(function(e) {if (e.keyCode == 27) escapePressed();});
//--><!]]>
</script>
</html>
Here is the bean code:
package de.example.beans;
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.ComponentSystemEvent;
import javax.faces.validator.ValidatorException;
import org.apache.log4j.Logger;
#ViewScoped
#ManagedBean
public class ResetBean implements Serializable
{
private static final long serialVersionUID = 7282752623428425109L;
private static final Logger log = Logger.getLogger(ResetBean.class);
protected String headline = null;
protected String message = null;
public ResetBean() {
log.error("ResetBean");
}
#PostConstruct
public void postConstruct() {
log.error("postConstruct");
}
#PreDestroy
public void preDestroy() {
log.error("preDestroy");
}
public void resetAction() {
log.error("resetAction");
headline = null;
message = null;
}
public void submitAction() {
log.error("submitAction headline="+headline+" message="+message);
}
public void validateForm(ComponentSystemEvent event) throws ValidatorException {
log.error("validateForm");
}
public String getHeadline() {
return headline;
}
public void setHeadline(String headline) {
this.headline = headline;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
Both the h:command button and the p:remoteCommand execute the same action in the same fashion. The difference is, that the h:command button responds to a mouse click, while the ESC key triggers the p:remoteCommand via javascript on using ESC key.
The problem is, that the route via p:remoteCommand seems to destroy the backing bean somehow (the bean is #ViewScoped). The #PreDestroy annotated method is never called, however: the next action on the page after using the p:remoteCommand forces the component to be created from scratch! Default constructor and #PostConstruct are called. Naturally some important parameters are missing now and the whole view gets shot to hell.
Any idea what is happening? Why the difference between p:remoteCommmand and h:commandButton in this instance? Any chance of working around the problem?
I could reproduce the problem. In my case and maybe the same case here (question provides only 'sample' code, not real one) it was caused by nested forms template->page.
If you have a ui:composition template or something similar to that, at the end of the generated HTML on client side it may creates nested forms like this:
<h:form>
...
<h:form>
...
</h:form>
...
</h:form>
which is invalid HTML code.
Remove unnecessary forms or reorganize code and test again. It should not call #postConstruct method when p:remoteCommand is called through JavaScript

Sending JSF textbox value to a managed bean function as a parameter [duplicate]

This question already has an answer here:
How to send form input values and invoke a method in JSF bean
(1 answer)
Closed 7 years ago.
I have two textboxes and one submit button in my login.xhtml page. I also have a bean. Here are the codes:
<?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">
<h:head>
<title>Welcome to Online Banking</title>
</h:head>
<h:body>
<h:outputText value="Online Banking System Login" ></h:outputText>
<h:form>
<h:panelGrid columns="2" border="1">
<h:outputText value="Username:"></h:outputText>
<h:inputText id="username" value="#{loginBean.username}"></h:inputText>
<h:outputText value="Password"></h:outputText>
<h:inputSecret id="password" value="#{loginBean.password}" > </h:inputSecret>
<h:commandButton value="Login" action="#{loginBean.loginCheck(username, password)}"></h:commandButton>
</h:panelGrid>
</h:form>
</h:body>
</html>
And the beans file:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package beans;
import javax.inject.Named;
import javax.enterprise.context.Dependent;
/**
*
* #author SUUSER
*/
#Named(value = "loginBean")
#Dependent
public class LoginBean {
/**
* Creates a new instance of LoginBean
*/
public LoginBean() {
}
private static String username="", password="";
public String getUsername(){
return username;
}
public String getPassword(){
return password;
}
public void setUsername(String Username){
username=Username;
}
public void setPassword(String Password){
password=Password;
}
public void loginCheck(String username, String password){
}
}
I will do the database check in my loginCheck function, so i need to pass the values of those two textboxes as a parameter. But i do not know how to do this. I just tried the code but it just passes empty strings as parameteres. Can anyone help me with this?
Thanks
Actually, you do not need to pass username and password parameters to a action method in your case.
A JSF page has a request life cycle. If you look inside JSF request life cycles, you will notice that values is applied to managed bean before the action.
Therefore, loginBean.username and loginBean.password values are set to managed bean username and password fields before the action. You can access them in the action method.
Your action will be
<h:commandButton value="Login" action="#{loginBean.loginCheck}"></h:commandButton>
and the action method
public String loginCheck(){
// search username and password in database.
// username, password field are set to values on page and accessible in the action method.
// Do not forget to navigate a proper page after according to login attempt.
}
For further reading
Communication in JSF 2.0 tutorial by BalusC
Basic Login Mechanism using Filters
JSF Request Life Cycle
How to pass value from textbox to Bean
1- create a .xhtml file
<h:form id="frm">
<h:inputText id="t1" value="#{user.x}" />
<h:commandButton action="#{user.check}" value="ok"/>
<h:outputText value="Value is #{user.msg}" ></h:outputText>
</h:form>
2- create a bean
ManagedBean(name="user")
RequestScoped
public class UserNumber {
int x;
String msg;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public void check()
{
if(x%2==0)
{
msg= "Even";
}
else
{
msg= "Odd";
}
}
public UserNumber() {
}
}
JSF automatically binds textbox values to variables in backing bean.
So you don't need to pass values to backing bean in calling function. You can just put like this
<h:commandButton value="Login" action="#{loginBean.loginCheck}"></h:commandButton>
And in bean you can use those as regular variable. I also suggest not to use static variables to store backing bean data.
public String loginCheck(){if(username == <fromDB> && password == <fromDB>) return "loginsuccess"; else return "loginfailure"; }
Hope this helps.
Well, from what I understand, do you that check in your loginCheck function the values of those textboxes. Automatically the JSF set the values of parameters to the variables, so you can work with them by gets(). For example is the following:
<h:form>
<h:panelGrid columns="2" border="1">
<h:outputText value="Username:"></h:outputText>
<h:inputText id="username" value="#{loginBean.username}"></h:inputText>
<h:outputText value="Password"></h:outputText>
<h:inputSecret id="password" value="#{loginBean.password}" > </h:inputSecret>
<h:commandButton value="Login" action="#{loginBean.loginCheck()}"></h:commandButton>
</h:panelGrid>
</h:form>
end in his ManagedBean is the following:
#ManagedBean(name= "loginBean")
public class LoginBean {
public LoginBean() {
}
// gets and sets
public void loginCheck(){
if(getUsername() != null && getPassword() != null){
// and here you chek database parameters
}
}
}

JSF commandButtons action value seems to be ignored - redirects to frontpage

I have a commandButton in JSF 2.0 with a actionvalue that I want to call a method in a bean and otherwise do nothing. However when I click on it, it redirects to the previous page.
This was programmed in java 1.7 in eclipse using glassfish 3.1.1.
Here is the code for the welcome.xhtml file where the commandButton is (showDetails) but there are many other files, so I have included a link to a WAR file so it is possible to check everything out. If i change the action attribute to point to a method that does not exist I will not get an error, I will again be redirected to the frontpage.
The program is started from the index.html file. After importing remember to leftclick on the project, go to properties>project facets and tick of JavaServerFaces 2.0
The relevant code:
welcome.xhtml
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!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:head>
<title>Insert title here</title>
</h:head>
<h:body>
<h3>#{userBean.user.name}</h3>
<hr />
<form>
<h:commandButton value="Back" action="index" />
</form>
<form>
<h:commandButton value="Show details" action="#{userBean.changeRenderDetails}" />
<h:panelGrid rendered="#{userBean.renderDetails}" columns="2">
<h:outputText value="Brugernavn:" /> #{userBean.user.name}
<h:outputText value="Password:" /> #{userBean.user.password}
</h:panelGrid>
</form>
</h:body>
</html>
userBean
package model;
import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
import javax.inject.Inject;
import javax.inject.Named;
#Named("userBean")
// or #ManagedBean(name="user")
#SessionScoped
public class UserBean implements Serializable {
// Oprettes når en bean oprettes
private User user = new User("", "");
#Inject
// Det nuværende service objekt initialiseres automatisk
private Service service;
public String validateUser() {
return service.validateUser(user);
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
//Lektion 10 - opg1
private boolean renderDetails;
public void changeRenderDetails(){
setRenderDetails(!isRenderDetails());
}
public boolean isRenderDetails() {
return renderDetails;
}
public void setRenderDetails(boolean renderDetails) {
this.renderDetails = renderDetails;
}
}
and the user class
package model;
public class User {
private String name;
private String password;
public User(String name, String password) {
super();
this.name = name;
this.password = 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;
}
}
navigation rules, none of which should have anything to do with the button which redirects to index.html:
<?xml version="1.0" encoding="UTF-8"?>
<faces-config
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee /web-facesconfig_2_0.xsd"
version="2.0">
<navigation-rule>
<from-view-id>/index.xhtml</from-view-id>
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>/welcome.xhtml</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>failure</from-outcome>
<to-view-id>/error.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
</faces-config>
As shown in every decent JSF book/tutorial, you should be using <h:form> instead of <form>.
<h:form>
<h:commandButton value="Back" action="index" />
</h:form>
<h:form>
<h:commandButton value="Show details" action="#{userBean.changeRenderDetails}" />
<h:panelGrid rendered="#{userBean.renderDetails}" columns="2">
<h:outputText value="Brugernavn:" /> #{userBean.user.name}
<h:outputText value="Password:" /> #{userBean.user.password}
</h:panelGrid>
</h:form>
See also
commandButton/commandLink/ajax action/listener method not invoked or input value not set/updated #1

Resources