gpt4 book ai didi

jsf - 调用 f :viewAction conditionally based on f:viewParam

转载 作者:行者123 更新时间:2023-12-04 21:19:44 31 4
gpt4 key购买 nike

我们有一个设置,我们将不同的可选 View 参数传递给 JSF 页面,并在设置参数后处理后续 View 操作。一个非常简单的例子如下所示:

page.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://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">

<f:view>
<f:metadata>
<f:viewParam name="a" value="#{page.a}"/>
<f:viewAction action="#{page.populateA()}" if="#{not empty page.a}"/>

<f:viewParam name="b" value="#{page.b}"/>
<f:viewAction action="#{page.populateB()}"/>
</f:metadata>

<h:outputLabel value="#{page.message}"/>
</f:view>
</html>

页面

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

@ViewScoped
@Named
public class Page {

private String a;

private String b;

private String message;

public String getA() {
return a;
}

public void setA(String a) {
this.a = a;
}

public String getB() {
return b;
}

public void setB(String b) {
this.b = b;
}

public String getMessage() {
return message;
}

public void populateA() {
this.message = "Param a given: " + this.a;
}

public void populateB() {
if (this.b != null) {
this.message = "Param b given: " + this.b;
}
}
}

现在,区别在于 a 的处理不起作用 (page.xhtml?a=123),而 b 的处理就像一个魅力( page.xhtml?b=123) - 尽管我认为我只是将空值检查从 Java 移到了 JSF。在可读性方面,我宁愿省略 Java 中的额外空值检查,并让 View 参数处理完全位于 JSF 中,但我如何调整代码才能使第一个场景起作用?

编辑 根据What is the purpose of rendered attribute on f:viewAction? 接受的答案, if 本身有效,所以我怀疑执行顺序错误(首先评估操作条件,然后将值应用于模型)。

最佳答案

<f:viewAction if>属性基本上是重命名为<h:xxx rendered>属性(我将留在中间是否更清楚,它至少有一个 bug in autogenerated documentation 作为结果;它列出了 rendered 而不是 if )因此在 < em>Apply Request Values 阶段与所有其他 UI 组件一样。此阶段调用 UIComponent#decode() View 中的所有 UI 组件。对于 UIViewAction <f:viewAction>后面的UI组件类标记, decode() 说明如下:

Take no action if any of the following conditions are true:

  • The current request is a postback and the instance has been configured to not operate on postback. See isOnPostback().

  • The condition stated in the if property evaluates to false. See isRendered()

所以,是的,关于“错误的执行顺序”,您确实是正确的。在 Apply Request Values 阶段,它会检查 if属性,如果它评估 false ,则不会进行解码,并且不会对操作事件进行排队。另请参阅 UIViewAction 的第 644 行source code它在哪里测试 isRendered()内部decode()如果 false 则不继续.在你的例子中,#{page.a} ,您正在检查 <f:viewAction if> ,仅在 更新模型值 阶段可用,该阶段 应用请求值 阶段。

您想测试保证在应用请求值 阶段可用的其他东西。最好的候选者是实际的请求参数本身。所有“普通”请求参数都在 implicit EL object 可用的 EL 范围内#{param}其中引用了 Map<String, String> 以参数名称作为键。

所以,总而言之,应该这样做:

<f:viewParam name="a" value="#{page.a}"/>
<f:viewAction action="#{page.populateA}" if="#{not empty param.a}"/>

更新以解决 <f:viewAction if> 的不直观行为, JSF 实用程序库 OmniFaces自 2.2 版起将提供 <o:viewAction>谁的if仅在 Invoke Application 阶段评估,就在广播操作事件之前。这个技巧是通过简单地扩展 UIViewAction 来完成的。组件并覆盖其 broadcast()isRendered()如下:

@Override
public void broadcast(FacesEvent event) throws AbortProcessingException {
if (super.isRendered()) {
super.broadcast(event);
}
}

@Override
public boolean isRendered() {
return !isImmediate() || super.isRendered();
}

这使您可以更直观地使用标签:

<f:viewParam name="a" value="#{page.a}"/>
<o:viewAction action="#{page.populateA}" if="#{not empty page.a}"/>

关于jsf - 调用 f :viewAction conditionally based on f:viewParam,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25241437/

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