Jsf 基于f:viewParam有条件地调用f:viewAction

Jsf 基于f:viewParam有条件地调用f:viewAction,jsf,jsf-2.2,viewaction,Jsf,Jsf 2.2,Viewaction,我们有一个设置,将不同的可选视图参数传递给JSF页面,并在设置参数后处理后续视图操作。下面是一个非常简单的示例: 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"> <

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

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>
现在,区别在于
a
的处理不起作用(page.xhtml?a=123),而
b
的处理就像一个符咒(page.xhtml?b=123)——尽管我认为我只是将空检查从Java移到了JSF。在可读性方面,我更愿意在Java中省略额外的空检查,并在JSF中完全定位视图参数处理,但是如何调整代码以使第一个场景工作

编辑根据接受的答案,
如果
本身有效,那么我怀疑执行顺序错误(首先评估动作条件,然后将值应用于模型)。属性基本上是一个重命名的
属性(我将在中间离开,不管它是否更清楚,它至少有一个结果,它列出了<代码>渲染< /代码>,而不是<代码>如果),因此在所有其他生命周期中完全相同的应用请求值阶段作为所有其他UI组件。视图中所有UI组件的。对于,
标记后面的UI组件类,描述如下:

如果以下任何情况为真,则不采取任何措施:

  • 当前请求是回发,实例已配置为不在回发时操作。请参阅

  • 如果属性的计算结果为false,则在
    中说明的条件。请参阅

因此,是的,关于“错误的执行顺序”,您确实是对的。在应用请求值阶段,它检查
if
属性,如果它计算
false
,则不会进行解码,操作事件也不会排队。另请参见
UIViewAction
的第644行,其中它测试
isRendered()
insice
decode()
,如果
false
,则不会继续。在您的情况下,您在
中检查的
{page.a}
仅在更新模型值阶段可用,该阶段在应用请求值阶段之后

您希望测试在应用请求值阶段保证可用的其他内容。最佳候选对象是实际的请求参数本身。所有“普通”请求参数都在
{param}
的EL范围内,它引用了一个以参数名称为键的

因此,总而言之,这应该做到:

<f:viewParam name="a" value="#{page.a}"/>
<f:viewAction action="#{page.populateA}" if="#{not empty param.a}"/>
这使您可以更直观地使用标记:

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

@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}"/>