I have now been banging my head for a while over a seemingly simple case. I have a Primefaces <p:inputText>
(as a cell inside a <p:dataTable>
) for which, when the value changes, I would like to get the value in my controller.
I cannot reveal the real code, only showing the vital excerpts of it:
<p:column headerText="Ratkaisu">
<p:inputText name="inpres" id="inpres" value="#{entity.resolution}">
<p:ajax event="change" immediate="true" execute="@this inpres" render="@this" listener="#{mainViewController.updateEntity}"/>
<f:param value="#{entity}" name="entity"/>
</p:inputText>
</p:column>
The "backing bean" is my mainViewController that is @ViewScoped The method receiving the ajax data inside the controller:
public void updateEntity(AjaxBehaviorEvent e) {
// I can get the entity via the parameter list
Entity entity = (Entity)FacesContext.getCurrentInstance()
.getExternalContext().getRequestMap().get(entity);
// The value below is always null
Object value = ((UIInput)e.getSource()).getValue();
....
}
Every time the text changes (enter of focus out of the text field), I get an ajax request to my method. Every time, I find the correct Entity from the request map, so the <f:param>
-part seems to work.
So my question (or maybe questions) is, that is it possible for me to get read the newly entered value of the InputText in the controller, via the AjaxBehaviorEvent or do I have to try something else (maybe setting the value of the inputText to the f:param)? Also checked that I did not find any values in the requestMap at the server side either...
I also checked what Chrome inspector is posting via ajax requests. I did not find any evidence that the text that I enter in the <p:inputText>
would be sent to the server.
Could anyone enlight or give me some pointers on this issue?
EDIT:
As @melloware pointed out, I made the client side example as minimal as possible, still fully running:
<!DOCTYPE html>
<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:p="http://primefaces.org/ui">
<f:view>
<h:head>
</h:head>
<h:body>
<h:form id="someid">
</h:form>
<p:inputText id="inpresx">
<p:ajax event="change" process="@this"
listener="#{mainViewController.doStuff}" />
</p:inputText>
</h:body>
</f:view>
</html>
for the MainViewController, the doStuff part:
public void doStuff(AjaxBehaviorEvent e) {
Object val = ((UIInput)e.getSource()).getValue();
// val is still null!
}
Even if the program now is very minimal, the value for the inputtext does not seem to be sent over to the server side. A strange thing IMO, is that i need those h:form-tags in order for the example to fire ajax requests.
Here is what the xhr POST request params look like when i feed TestingTesting to the inputtext and press enter (using Chrome Inspector):
javax.faces.partial.ajax: true
javax.faces.source: inpresx
javax.faces.partial.execute: inpresx
javax.faces.behavior.event: change
javax.faces.partial.event: change
someid: someid
javax.faces.ViewState: -4351418361364308383:4652862949343904732
From the above data being sent, there seems like no text data from the inputtext is communicated over to the server side. What may I have done wrong?
EDIT 2:
tldr; The actual solution to the problem for me was to wrap my table inside a form. The ajax tag won't work if there is no form tag that WRAPS it at some level.
Here is my fully working example. Whatever I type in the inputtext like "hello" comes out the in System.out.println.
<!DOCTYPE html>
<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:p="http://primefaces.org/ui"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>PrimeFaces Test</title>
</h:head>
<h:body>
<h:form id="frmTest">
<p:inputText id="inpresx" value="#{testView.testString}" >
<p:ajax event="change" process="@this" listener="#{testView.doStuff}" />
</p:inputText>
</h:form>
</h:body>
</html>
Java:
package org.primefaces.test;
import javax.faces.event.AjaxBehaviorEvent;
import javax.faces.component.UIInput;
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
@ManagedBean(name = "testView")
@ViewScoped
public class TestView implements Serializable {
private String testString;
public void doStuff(AjaxBehaviorEvent e) {
Object val = ((UIInput)e.getSource()).getValue();
System.out.println("Value = " + val);
}
public String getTestString() {
return testString;
}
public void setTestString(String testString) {
this.testString = testString;
}
}
And my Chrome Output:
javax.faces.partial.ajax: true
javax.faces.source: frmTest:inpresx
javax.faces.partial.execute: frmTest:inpresx
javax.faces.behavior.event: change
javax.faces.partial.event: change
frmTest: frmTest
frmTest:inpresx: stackoverflow
javax.faces.ViewState: 9209410033241115450:-5298602114910206430