This question already has answers here:
Why my jsf <h:inputText> dont set the value in bean class?
(2 answers)
commandButton/commandLink/ajax action/listener method not invoked or input value not set/updated
(12 answers)
Closed 4 years ago.
I have no idea why my setters are not invoked while processing form. I see in network browser tool, that POST request is fired with correct (updated) data. But it doesn't affects my binded bean.
<p:commandButton value="Action"
immediate="true"
action="#{beanView.actionForString('5/13/015')}"
oncomplete="PF('some_widget').show()"
update="some_widget_update"/>
<p:dialog id="some_widget_update" widgetVar="some_widget" width="800">
<ui:include src="/view.xhtml" />
</p:dialog>
Template form:
<h:form id="contentForm"
prependId="false"
enctype="multipart/form-data">
<p:messages autoUpdate="true"
globalOnly="true"
showDetail="true"
for="formMessages"
closable="true" />
<div id="starterDiv"
class="ui-fluid">
<ui:insert name="formAsd" />
</div>
</h:form>
And view.xhtml:
<ui:define name="formAsd">
<h:panelGroup rendered="#{beanView.payment!= null}">
<c:set var="payment" value="#{beanView.payment}" />
<div class="ui-g with_background">
<div class="ui-g-2">Payment Id:</div>
<div class="ui-g-2">
<p:inputText value="#{payment.id}"/>
</div>
</div>
<p:commandButton value="Save"
immediate="true"
process="contentForm"
action="#{beanView.save()}" style="width: 150px"/>
</h:panelGroup>
</ui:define>
The bean view looks like that:
#ManagedBean
#ViewScoped
#Data
#FieldDefaults(level = AccessLevel.PRIVATE)
public class BeanView implements Serializable {
Payment payment;
#Setter(onMethod=#__({#Autowired}))
transient PaymentService paymentService;
public void save() {
paymentService.registerPayment(payment); // here It's unchanged!!
}
public void actionForString(String asd) {
payment= paymentService.takeForString(asd)
}
}
Getter works fine, I can see values which service returns in my view.xhtml. Then as I said above, after changing the input value and clicking save button, my debugger shows old value (from intialization in actionFroString) method. Why it is happening?
I believe your problem is immediate="true" on your Command Button. That command immediate="true" tells JSF to skip the validation and binding phase which is why your setters are not being called. This detailed explanation explains why: https://dzone.com/articles/jsf-and-immediate-attribute
myBean is in request scope.
<h:form id="indexFormID">
<a4j:outputPanel ajaxRendered="true" layout="block">
<h:inputText id="inputForHD" value="#{myBean.inputParam}"></h:inputText>
<a4j:commandLink value="Submit" action="#{myBean.myMethod}" reRender="renderSuccess" process="indexFormID:inputForHD"></a4j:commandLink>
</a4j:outputPanel>
<h:panelGroup id="renderSuccess">
<h:panelGroup rendered="#{myBean.someBoolean}">
//Some other JSF components go here
</h:panelGroup>
</h:panelGroup>
</h:form>
MyBean class definition:
private String inputParam;
//Getters and setters are there
public String myMethod()
{
log.debug("~ Value of inputParam" +this.getInputParam()); //This is printing null value for inputParam
//when commandLink is clicked
return null;
}
Why my inputParam is not getting set with the input parameters?
Ok I found few issues with your approach:
<h:inputText id="inputForHD" value="#{myBean.inputParam}"></h:inputText>
You are already mapping the inputParam attribute with this bean, why have a new Id "inputForHD"
Use the inputParam itself, if you want to use inputForHD, you can pick the same from request Parameter map like.
String inputForHD = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("indexFormID:inputForHD");
Also as I mentioned previously wrap the output panel inside the and a4j panel e.g.
<h:panelGroup id="renderSuccess">
<h:panelGroup rendered="#{helloWorld.someBoolean}">
//Some other JSF components go here
<h:inputText id="inputForHDasdasd" value="#{helloWorld.inputParam}"></h:inputText>
</h:panelGroup>
</h:panelGroup>
This is working fine, let know if any issues.
This question already has answers here:
commandButton/commandLink/ajax action/listener method not invoked or input value not set/updated
(12 answers)
Closed 7 years ago.
I am using Primefaces 3.4.2.
I have the following in my JSF page
<p:selectOneMenu id="emp" value="#{mymb.emp.employeeName}"
valueChangeListener="#{mymb.handleChange}"
required="true"
style="width: 150px;">
<f:selectItem noSelectionOption="true"
itemLabel="Please Select"/>
<f:selectItems value="#{mymb.employeeList}" var="emp"
itemLabel="#{emp.employeeName}"
itemValue="#{emp.employeeNumber}"/>
<p:ajax update="sublist"/>
</p:selectOneMenu>
and in ManagedBean
public void handleChange(ValueChangeEvent event){
System.out.println("here "+event.getNewValue());
}
The problem is valueChangeListener is not firing, i.e. handleChange method is not getting invoked. I tried with the following, but it is not working either.
<p:ajax update="sublist" listener="#{mymb.handleChange}" />
Separate JSF page:
<ui:composition template="/templates/layout.xhtml"
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"
xmlns:p="http://primefaces.org/ui">
<ui:define name="content">
<h:head>
</h:head>
<h:body>
<h:form id="form">
<p:panelGrid columns="6">
<h:outputLabel value="Employees" for="employees" />
<p:selectOneMenu id="employees"
value="#{mymb.employeesList}"
required="true">
<f:selectItems value="#{mymb.employeesList}" var="emp"
itemLabel="#{emp.employeeName}" />
<p:ajax listener="#{mymb.handleChange}" />
</p:selectOneMenu>
</p:panelGrid>
</h:form>
</h:body>
</ui:define>
</ui:composition>
If you want to use valueChangeListener, you need to submit the form every time a new option is chosen. Something like this:
<p:selectOneMenu value="#{mymb.employee}" onchange="submit()"
valueChangeListener="#{mymb.handleChange}" >
<f:selectItems value="#{mymb.employeesList}" var="emp"
itemLabel="#{emp.employeeName}" itemValue="#{emp.employeeID}" />
</p:selectOneMenu>
public void handleChange(ValueChangeEvent event){
System.out.println("New value: " + event.getNewValue());
}
Or else, if you want to use <p:ajax>, it should look like this:
<p:selectOneMenu value="#{mymb.employee}" >
<p:ajax listener="#{mymb.handleChange}" />
<f:selectItems value="#{mymb.employeesList}" var="emp"
itemLabel="#{emp.employeeName}" itemValue="#{emp.employeeID}" />
</p:selectOneMenu>
private String employeeID;
public void handleChange(){
System.out.println("New value: " + employee);
}
One thing to note is that in your example code, I saw that the value attribute of your <p:selectOneMenu> is #{mymb.employeesList} which is the same as the value of <f:selectItems>. The value of your <p:selectOneMenu> should be similar to my examples above which point to a single employee, not a list of employees.
The valueChangeListener is only necessary, if you are interested in both the old and the new value.
If you are only interested in the new value, the use of <p:ajax> or <f:ajax> is the better choice.
There are several possible reasons, why the ajax call won't work. First you should change the method signature of the handler method: drop the parameter. Then you can access your managed bean variable directly:
public void handleChange(){
System.out.println("here "+ getEmp().getEmployeeName());
}
At the time, the listener is called, the new value is already set. (Note that I implicitly assume that the el expression mymb.emp.employeeName is correctly backed by the corresponding getter/setter methods.)
Another solution is to mix valueChangeListener, ajax and process:
<p:selectManyCheckbox id="employees" value="#{employees}" columns="1" layout="grid" valueChangeListener="#{mybean.fireSelection}" >
<f:selectItems var="employee" value="#{employeesSI}" />
<p:ajax event="valueChange" immediate="true" process="#this"/>
</p:selectManyCheckbox>
Method in mybean is just :
public void fireSelection(ValueChangeEvent event) {
log.debug("New: "+event.getNewValue()+", Old: "+event.getOldValue());
}
Like this, valueChangeEvent is very light !
PS: Works fine with PrimeFaces 5.0
<p:ajax listener="#{my.handleChange}" update="id of component that need to be rerender after change" process="#this" />
import javax.faces.component.UIOutput;
import javax.faces.event.AjaxBehaviorEvent;
public void handleChange(AjaxBehaviorEvent vce){
String name= (String) ((UIOutput) vce.getSource()).getValue();
}
All can be defined as in f:ajax attiributes.
i.e.
<p:selectOneMenu id="employees" value="#{mymb.employeesList}" required="true">
<f:selectItems value="#{mymb.employeesList}" var="emp" itemLabel="#{emp.employeeName}" />
<f:ajax event="valueChange" listener="#{mymb.handleChange}" execute="#this" render="#all" />
</p:selectOneMenu>
event: it can be normal DOM Events like click, or valueChange
execute: This is a space separated list of client ids of components that will participate in the "execute" portion of the Request Processing Lifecycle.
render: The clientIds of components that will participate in the "render" portion of the Request Processing Lifecycle. After action done, you can define which components should be refresh. Id, IdList or these keywords can be added: #this, #form, #all, #none.
You can reache the whole attribute list by following link:
http://docs.oracle.com/javaee/6/javaserverfaces/2.1/docs/vdldocs/facelets/f/ajax.html
Try using p:ajax with event attribute,
My problem were that we were using spring securyty, and the previous page doesn't call the page using faces-redirect=true, then the page show a java warning, and the control doesn't fire the change event.
Solution:
The previous page must call the page using, faces-redirect=true
this works for me:
It can be used inside the dialog, but the dialog canĀ“t be inside any componet such as panels, accordion, etc.
I've been using JSF for a while but there's something that has always confused me. Hopefully someone can help.
Simple example, there's a page that shows a table of "Person"s and when you click on the "Person" name, it takes you to a page to view the details of the "Person".
Typically, I implement a personSearch.jsf page like this:
<h:dataTable value="#{personHandler.persons}" var="person">
<h:column>
<h:commandLink action="#{personHandler.show( person.id )}" >
<h:outputText value="#{person.name}" />
</h:commandLink>
</h:column>
</h:dataTable>
And I implement a personView.jsf page like this:
<h:panelGrid columns="2">
<h:outputText value="Person ID:" />
<h:outputText value="#{personHandler.selectedPerson.id}" />
<h:outputText value="Person Name:" />
<h:outputText value="#{personHandler.selectedPerson.name}" />
</h:panelGrid>
PersonHandler.show(Integer personId) sets personHandler.selectedPerson and then redirects to the personView page.
This all works fine when PersonHandler is a session bean. But I prefer it to be a request scoped bean because the user may have several windows open and I don't want there to be only one selected person per session.
So my question is, what's the "correct" way to do this JSF? I was once able to get what I wanted using a4j:keepAlive on the personHandler, but that always felt like a kludge. Again, this is something I've never understood about JSF.
Any help is greatly appreciated!
rob
If the view is supposed to be bookmarkable, pass the person ID as a GET request parameter instead of a POST request "parameter".
<h:outputLink value="viewperson.xhtml">
<f:param name="id" value="#{person.id}" />
</h:outputLink>
This way you can use two #RequestScoped beans, one for the list and one for the view. You can preload the selected person as follows:
#ManagedProperty(value="#{param.id}")
private Long id;
#PostConstruct
public void init() {
selectedPerson = personDAO.find(id);
}
If it is not supposed to be bookmarkable, then just create a single view which renders the view state conditionally.
<ui:fragment rendered="#{!personHandler.viewMode}">
<h:form>
<h:dataTable value="#{personHandler.persons}" var="person">
<h:column>
<h:commandLink value="#{person.name}" action="#{personHandler.show(person)}" />
</h:column>
</h:dataTable>
</h:form>
</ui:fragment>
<ui:fragment rendered="#{personHandler.viewMode}">
<h:form>
...
<h:commandLink value="Go back" action="#{personHandler.back}" />
</h:form>
</ui:fragment>
(You can if necessary split out the content of the both framgents to another Facelet files which you include by <ui:include>)
This way you can use a single #ViewScoped bean with action methods returning void or null.
public void show(Person selectedPerson) {
this.selectedPerson = selectedPerson;
}
public void back() {
selectedPerson = null;
}
public boolean isViewMode() {
return selectedPerson != null;
}
You can even wrap the whole view in some
<h:panelGroup id="container">
and nest the following in both command links to let Ajax magic do the work
<f:ajax execute="#form" render=":container" />
In JSF, we can bind HtmlDataTable to backing bean and get the row data. But ui:repeat doesn't even have a binding attribute. So, how do I know which row (element) is clicked in ui:repeat?
Either use f:setPropertyActionListener
<h:form>
<ui:repeat value="#{bean.items}" var="item">
<h:outputText value="#{item.value}">
<h:commandButton value="submit" action="#{bean.submit}">
<f:setPropertyActionListener target="#{bean.item}" value="#{item}"/>
</h:commandButton>
</ui:repeat>
</h:form>
with
private List<Item> items;
private Item item;
public void submit() {
System.out.println(item);
}
Or just put action method in iterated item
<h:form>
<ui:repeat value="#{bean.items}" var="item">
<h:outputText value="#{item.value}">
<h:commandButton value="submit" action="#{item.submit}" />
</ui:repeat>
</h:form>
Either case, you need to ensure that the same items is preserved in subsequent request.
Both ways by the way also just works in a h:dataTable.