5

我正在用 Java EE 6 编写一个应用程序,并使用 Primefaces 3.4.1 作为用户界面。

我有类似的东西。

通用页面.xhtml

<ui:composition template="mainApplicationTemplate.xhtml" [...]>
    <p:tabView id="tabView" dynamic="false"cache="false">
        <p:tab id="tab1" title="Tab 1">
            <h:form id="form1">
                ...
            </h:form>
        </p:tab>
        <p:tab id="tab1" title="Tab 1">
            <h:form id="form2">
                ...
            </h:form>
        </p:tab>
    </p:tabView>
<ui:composition >

child1.xml

<ui:composition template="genericPage.xhtml" ...>
    <ui:param name="actionBean" value="#{actionBeanA}"/>
</ui:compisition>

child2.xml

<ui:composition template="genericPage.xhtml" ...>
    <ui:param name="actionBean" value="#{actionBeanB}"/>
</ui:compisition>

其背后的想法是 child1.xhtml 和 child2.xhtml 共享相同的 jsf 代码,都包含在 genericPage.xhtml 中,但它们具有不同的后端 bean(由“actionBean”参数化)

到目前为止,效果非常好。当我将 ui 参数放在<p:ajax/>元素中时,它会变得复杂。

从后端 bean 中,我需要以编程方式更新活动选项卡,而另一个保持不变。为此,我需要将活动选项卡存储在操作 bean 中,当某些外部事件发生时,操作 bean 会更新活动选项卡。

请注意,由于其他一些因素:

  • 我无法dynamic="true"设置tabView
  • 我不能有一个全局表单tabView,因此不能使用“activeIndex”属性(我在应用程序的其他部分中这样做)来管理活动选项卡。

我想做的事

为了解决这个问题,我想使用元素的tabChange事件:tabView

<p:tabView id="tabView" dynamic="false"cache="false">
        <p:ajax event="tabChange" listener="#{actionBean.listen}"
        <p:tab id="tab1" title="Tab 1">
            <h:form id="form1">
                ...
            </h:form>
        </p:tab>
        <p:tab id="tab1" title="Tab 1">
            <h:form id="form2">
                ...
            </h:form>
        </p:tab>
    </p:tabView>

行动豆

@Named
@WindowScoped
public class ActionBeanA implements Serializable{
    public void listen(TabChangeEvent event){
        ...
    }

}

什么不起作用

当我这样做时,我得到了错误

Target Unreachable, identifier 'actionBean' resolved to null: javax.el.PropertyNotFoundException: Target Unreachable, identifier 'actionBean' resolved to null

这似乎表明该<p:ajax>元素尚未通过操作 bean,因此不知道是什么actionBean

但是,如果我像这样更改侦听器方法的签名

<p:ajax event="tabChange" listener="#{actionBean.listen(anything)}"

并将后端 bean 更改为:

public void listen(TabChangeEvent event){
    System.out.println(event.toString());
}

这样做,我没有得到目标无法访问的错误,而是listen方法中的空指针异常(因为我没有为“任何东西”赋值)。这表明在这种情况下,<p:ajax/>元素知道是什么actionBean并设法调用 bean 中的方法。

问题

我怎么能解决这个问题?我希望能够在选项卡更改事件中向我的后端 bean 发送新的活动选项卡。

4

2 回答 2

6

我也遇到了这个问题,并在 Primefaces 问题跟踪器中找到了解决方案:在帖子 #20 中找到的解决方案

总而言之,这是 Primefaces 中的一个已知问题。半修复可在 3.4.2 版中找到,需要对代码进行一些更改。目前你有:

public void listen(TabChangeEvent event){
    System.out.println(event.toString());
}

哪个不起作用。您应该将代码更改为:

public void listen(AjaxBehaviorEvent event){
    System.out.println(event.toString());
}

如果您需要使用特定的方法,TabChangeEvent那么您需要进行强制转换:(TabChangeEvent)event.

它在问题跟踪器上具有固定状态,因此可能需要将此作为永久解决方案。

于 2013-01-23T14:29:11.663 回答
-1

值和方法表达式处理之间存在差异。对于后者,您需要稍后在 Facelet 上下文中使用该参数。

要将参数的值包含到 facelet 上下文中,您只需将参数值定义放在<f:metadata>标记内。

另外,请注意<f:metadata>标签应该始终是标签的直接子<f:view>标签,所以我会做这样的事情:

模板.xhtml

<f:view ....>
    <ui:insert name="metadata"/>
    ....
</f:view>

childPage.xhtml

<ui:composition template="/WEB-INF/template.xhtml">
    <ui:define name="metadata">
        <f:metadata>
            <ui:param name="actionBean" value="#{actionBeanA}"
        </f:metadata>
    </ui:define>
</ui:composition>

完成此操作后,您可以在template.xhtml没有变通方法的情况下以原始方式使用 listener 属性,并且将始终使用适当的事件类型参数调用您的方法。

于 2013-04-08T14:08:28.663 回答