gpt4 book ai didi

ajax - 为什么第一个 AJAX 调用会重置我的 View 参数?

转载 作者:行者123 更新时间:2023-12-04 00:56:49 30 4
gpt4 key购买 nike

我无法找出为什么第一次 ajax 调用会导致我的视​​图参数的 setter 被再次调用,而每个后续调用都不会再次调用 setter 。

我有以下简单的 View bean:

package test;

import java.io.Serializable;

import javax.faces.view.ViewScoped;
import javax.inject.Named;

@Named
@ViewScoped
public class TestController implements Serializable {

private static final long serialVersionUID = 1L;

String param;

public String getParam() {
return param;
}

public void setParam(String param) {
System.out.println("param set to " + param);
this.param = param;
}
}

我还有一个非常基本的 .xhtml 页面,它只包含一个按钮:

<?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://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">

<h:head></h:head>

<f:metadata>
<f:viewParam id="param" name="param" value="#{testController.param}"/>
</f:metadata>

<h:form id="form">
<h:commandButton id="button" value="Test">
<f:ajax execute="@this"></f:ajax>
</h:commandButton>
</h:form>

</html>

现在,在测试此页面时,我在浏览器中调用 https://localhost:8443/test/test.xhtml?param=foo。正如我所料,日志声称 View 参数设置为“foo”。现在我挣扎的地方是,当我第一次按下按钮时,日志再次声称参数设置为“foo”,证明再次调用了 setter 。我不明白为什么ajax请求再次设置了 View 参数。让我感到困惑的是,任何后续的按钮点击都不会再次调用 View 参数的 setter ,尤其是第一次调用和所有后续调用看起来完全一样。

所以我的问题是:

  • 为什么在第一次 ajax 调用时调用 View 参数的 setter ,但在后续调用中却没有?
  • 有什么办法可以防止这种行为吗?

我正在使用 Mojarra 2.3.9.SP06 的 Wildfly 19 上运行示例,如果有任何帮助的话。

编辑 1:为了更清楚,为什么这个问题不同于 f:viewParam lost after ajax call .另一个问题询问为什么 View 参数在第一次 ajax 调用后丢失以及如何始终发送它们。这是一个完全相反的问题:为什么 View 参数是第一次发送,如何防止这种情况发生?

另一个问题的答案声称可以调用 FacesContext.getCurrentInstance().isPostback()。我知道这一点。虽然它当然在检测 ajax 召回的意义上起作用,并且使我能够在这种情况下不重置 View 参数,但它不会阻止 View 参数的 setter 首先被调用。这是我理想中想要实现的。我也会满足于至少理解为什么 View 参数在第一次 ajax 调用时被不同对待。我想我在概念上还没有理解某些东西。

编辑 2: 我在 https://github.com/eclipse-ee4j/mojarra/issues/4714 下提交了错误报告.

最佳答案

您在概念上没有任何误解。我也不明白。

我目前仍在调查为什么 setter 在第一个且仅在第一个 ajax 回调中被调用。我本来希望它总是或永远不会被调用。 @fuggerjaki61 的分析在某种程度上是正确的,但它似乎与围绕 null 或未提交值的更大问题有关。

可以在最简单的解决方案中阅读大量信息:OmniFaces o:viewParam而不是 f:viewParam

并使用

<o:viewParam id="param" name="param" value="#{testController.param}"/>

(不要忘记声明 xmlns:o="http://omnifaces.org/ui",但既然你应该 ;-) 无论如何都要使用 OmniFaces,我认为它已经存在了 :-) )

根据我阅读的所有信息,我认为可能是设置

<context-param>
<param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
<param-value>true</param-value>
</context-param>

也可能解决它,但事实并非如此。 setter 在第一次 ajax 调用时仍然使用旧值调用,在第二次和后续调用中,如果未提交,它只会显式地将值设置为 null。也不是您想要的。

更多详情

@fuggerjaki61 的解决方案可能有效,但我不确定在其他情况下的后果,因为我还可以通过更改其他内容但破坏其他情况来修复此问题。如果我尝试将 o:viewParam 的基础知识与 f:viewParam 进行比较,提交的值(在另一个答案中由 @fuggerjaki61 引用)确实发挥了作用。它保存在本地 o:viewParam

@Override
public String getSubmittedValue() {
return submittedValue;
}

@Override
public void setSubmittedValue(Object submittedValue) {
this.submittedValue = (String) submittedValue; // Don't delegate to statehelper to keep it stateless.
}

在 f:viewParam 中,它被读取并设置为 stateHelper

@Override
public Object getSubmittedValue() {
return getStateHelper().get(PropertyKeys.submittedValue);
}

/**
* PENDING (docs) Interesting that submitted value isn't saved by the parent
* @param submittedValue The new submitted value
*/
@Override
public void setSubmittedValue(Object submittedValue) {
getStateHelper().put(PropertyKeys.submittedValue, submittedValue);
}

在这里阅读 java 文档,我个人会说你的问题中的“为什么”看起来好像某处有错误(或遗漏),尚未确定,但意外或明确解决了 o:viewParam

关于ajax - 为什么第一个 AJAX 调用会重置我的 View 参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61762633/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com