(如何)可以通过 AjaxBeahviorEvent 获取 UIInput 的值以获取已更改的 inputText

(How) Can one obtain the value of a UIInput via an AjaxBeahviorEvent for a changed inputText

为了一个看似简单的案例,我已经苦思冥想了一段时间。我有一个 Primefaces <p:inputText>(作为 <p:dataTable> 中的一个单元格),当值发生变化时,我想在我的控制器中获取该值。 我不能透露真正的代码,只展示它的重要摘录:

<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>

"backing bean" 是我的 mainViewController,即 @ViewScoped 控制器内部接收ajax数据的方法:

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();
    ....
}

每次文本更改(焦点输入超出文本字段)时,我都会收到对我的方法的 ajax 请求。每次,我都会从请求映射中找到正确的实体,因此 <f:param> 部分似乎有效。

所以我的问题(或可能是问题)是,我是否有可能通过 AjaxBehaviorEvent 读取控制器中 InputText 的新输入值,或者我是否必须尝试其他方法(可能设置inputText 的值到 f:param)?还检查了我在服务器端的 requestMap 中也没有找到任何值...

我还检查了 Chrome 检查员通过 ajax 请求发布的内容。我没有找到任何证据表明我在 <p:inputText> 中输入的文本会被发送到服务器。

任何人都可以启发或给我一些关于这个问题的指示吗?

编辑:

正如 @melloware 所指出的,我将客户端示例尽可能地精简,但仍完整 运行:

<!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>

对于 MainViewController,doStuff 部分:

public void doStuff(AjaxBehaviorEvent e) {
    Object val = ((UIInput)e.getSource()).getValue();
    // val is still null!
}

即使现在的程序非常小,输入文本的值似乎也没有发送到服务器端。在我看来,一件奇怪的事情是我需要那些 h:form-tags 才能让示例触发 ajax 请求。

这是当我将 TestingTesting 提供给输入文本并按回车键(使用 Chrome Inspector)时 xhr POST 请求参数的样子:

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

从上面发送的数据来看,似乎没有来自输入文本的文本数据被传送到服务器端。我可能做错了什么?

编辑 2:

tldr; 对我来说,问题的实际解决方案是将我的 table 包装在一个表单中。如果没有在某种程度上包装它的表单标签,ajax 标签将不起作用。

这是我的完整示例。无论我在 "hello" 之类的输入文本中输入什么,都会在 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;
    }
}

我的 Chrome 输出:

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: Whosebug
javax.faces.ViewState: 9209410033241115450:-5298602114910206430