在组件绑定上绑定 f:viewParam

Binding f:viewParam on component binding

我想创建 <f:viewParam> 来设置 <p:tabView> 的活动选项卡。 在我的页面中,我定义了一个 <f:viewParam>:

<f:viewParam name="tab" value="#{tabView.activeIndex}" />

<p:tabView>binding:

<p:tabView binding="#{tabView}">
    <p:tab title="tab1" />
    <p:tab title="tab2" />
    <p:tab title="tab3" />
</p:tabView>

但它不起作用。如果我用参数 ?tab=1 打开我的页面,我会看到这个异常:

Caused by: javax.el.PropertyNotFoundException: Target Unreachable, identifier 'tabView' resolved to null

为什么会这样?

P.S.: 除了@BalusC 的回答,你还可以像这样在 viewMap 上使用绑定组件 属性:

<f:viewParam name="tab" value="#{viewScope['activeTabIndex']}" />

<p:tabView activeIndex="#{viewScope['activeTabIndex']}">
    <p:ajax event="tabChange" />
    <p:tab title="tab1" />
    <p:tab title="tab2" />
    <p:tab title="tab3" />
</p:tabView>

在这种情况下,您必须通过 <p:ajax event="tabChange" />dynamic="true" cache="false"

激发 ajax-请求将值放入 viewMap

那是因为此时尚未构建视图,因此尚未评估所有 binding 属性。这确实有点出乎意料,但在 GET 请求中,视图默认仅在呈现响应阶段构建。当请求是回发时它工作正常,因为根据定义视图已经在恢复视图阶段构建。

我可以想到两个解决方法:

  1. <f:viewParam value> 移动到 <f:event type="preRenderView" listener>。在 GET 请求中,视图在此时保证已构建。

    <f:metadata>
        <f:viewParam name="tab" />
        <f:event type="preRenderView" listener="#{tabView.setActiveIndex(tab)}"/>
    </f:metadata>
    

    这是有效的,因为没有 value<f:viewParam> 默认情况下会将转换和验证的请求参数值作为请求属性放在完全相同的名称 #{tab} 下。您只需要确保您没有同名的请求范围托管 beans,否则它可能会发生冲突。

  2. 如果不需要转换和验证,直接传#{param.tab}就可以了

    <f:metadata>
        <f:event type="preRenderView" listener="#{tabView.setActiveIndex(param.tab)}"/>
    </f:metadata>
    

顺便说一下,这个方法不错。

另请参阅: