【问题标题】:(How) Can one obtain the value of a UIInput via an AjaxBeahviorEvent for a changed inputText(如何)可以通过 AjaxBeahviorEvent 获取 UIInput 的值以获取更改的 inputText
【发布时间】:2018-07-05 13:03:24
【问题描述】:

我现在一直在为一个看似简单的案例而苦苦挣扎。我有一个 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>

“支持 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 请求。每次,我都会从请求映射中找到正确的实体,所以&lt;f:param&gt;-part 似乎可以工作。

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

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

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

编辑:

正如 @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!
}

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

当我将 TestingTesting 输入到 inputtext 并按 Enter(使用 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

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

编辑 2:

tldr; 对我来说,这个问题的实际解决方案是将我的表格包裹在一个表格中。如果没有表单标签在某个级别包裹它,则 ajax 标签将不起作用。

【问题讨论】:

  • 我在下面更新了我的答案,并在 PF 6.2 上为我工作了一个完整的示例
  • 另外,您似乎没有将 someId
    包裹在
    周围
  • 好吧,看起来我是否将表单包裹起来并不重要。此外,在更复杂的示例中,我无法在表格周围添加任何额外的表单
  • 这(可能)不是重复的。实际上,我尽量避免使用表单,但似乎必须以某种方式包含它,以便启用 ajax(我可能在这里错了)。在现实生活中的应用程序中,我的输入位于表格中(作为单元格),并且在任何情况下都不得刷新页面。而且,出于这个目的,我不想(?)直接映射到支持 bean。我只是觉得很奇怪,更改后的值没有传达给服务器端......

标签: ajax jsf primefaces jsf-2 jsf-2.2


【解决方案1】:

这是我的完整工作示例。无论我在输入文本中输入什么,例如“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: stackoverflow
javax.faces.ViewState: 9209410033241115450:-5298602114910206430

【讨论】:

  • 我相信@this是默认的,所以根本不需要。
  • 其实最开始的ajax只包含eventlistener。我的问题中的一些属性是反复试验的遗物。现在我已经尝试了很多不同的解决方案,以至于我开始认为问题可能出在其他地方。我的代码在 p:dialog 内的 p:tabView 内的 p:tab 内。我原本没有写代码,只是添加了这个功能。问题可能是,有 Html-DIV 包装了一些东西吗?这会以某种方式破坏 JSF 树吗?我的 ajax 调用确实到达服务器,但服务器端源的值产生 null
  • 关于选项 3.,我的实体已分离,我想在输入的数据更改时保留数据(而不是按“保存”按钮)。我仍然对仅仅读取 ajax 事件的输入值有多难感到困惑。正如我在原帖中所说,使用 Chrome Inspector,我找不到证据表明数据是根据 ajax 请求发送到服务器端的。
  • 好的,如果您的实体已分离,我明白您为什么希望侦听器保存数据。对我来说,它告诉我 JSF 绑定阶段以某种方式验证失败并且实际上没有发送值。也许尝试创建一个简单的页面,其中包含一个小得多的示例,将该页面的其余部分排除在外。我喜欢不断缩小范围,直到我拥有最小的可重现样本。这可能会帮助你弄清楚。
  • 是的,minimal reproducible example 应该始终用于调试。为了你自己和我们
猜你喜欢
  • 2016-09-27
  • 2020-11-01
  • 1970-01-01
  • 2023-03-24
  • 2021-10-01
  • 1970-01-01
  • 2012-02-17
  • 1970-01-01
  • 2014-02-15
相关资源
最近更新 更多