如何有条件地渲染 <f:facet>?

Posted

技术标签:

【中文标题】如何有条件地渲染 <f:facet>?【英文标题】:How do I conditionally render an <f:facet>? 【发布时间】:2011-05-21 03:01:29 【问题描述】:

我希望能够有条件地从 PrimeFaces 面板元素中省略页脚:

<p:panel header="some text">
    <f:facet name="footer">
        #message
    </f:facet>
    <!-- ... -->
</p:panel>

我希望rendered 属性能起作用:

<p:panel header="some text">
    <f:facet name="footer" rendered="#!empty message">
        #message
    </f:facet>
    <!-- ... -->
</p:panel>

但页脚仍然呈现,内容为空。 facet 似乎没有rendered 属性:http://www.jsftoolbox.com/documentation/help/12-TagReference/core/f_facet.html

正确的做法是什么?

【问题讨论】:

我做了一些测试:没有任何内容的页脚(允许空白)不会被渲染。一个带有 any 内容的页脚,即使它是一个返回 null/empty 的简单 EL,它也会呈现页脚。我不确定需要哪种行为,可能值得在 PF 问题跟踪器上报告:code.google.com/p/primefaces/issues @BalusC:好像是错误报告时间。 【参考方案1】:

这是我在尝试有条件地在复合组件中渲染构面时所做的。

<composite:interface>
    <composite:facet name="header" required="false" />
</composite:interface>
<composite:implementation>
    <p:panel>
        <c:if test="#empty component.facets.header" >
            <f:facet id="#cc.attrs.id_default_header" name="header">
            all sorts of stuff here
            </f:facet>
        </c:if>
        <c:if test="#not empty component.facets.header">
            <composite:insertFacet id="#cc.attrs.id_custom_header" name="header" />
        </c:if>
        <composite:insertChildren id="#cc.attrs.id_content"/>
    </p:panel>
</composite:implementation>

这让复合组件的用户在需要时提供标题方面,如果他们不提供,我们提供默认值。显然,您不能提供默认值,而不能做任何事情。

这在 jsf 控件中混合了 c:if,但我们没有看到任何不利影响。

【讨论】:

有趣。我想到了这一点,但由于我没有测试它的环境,我担心在那里混合c:if 不会像预期的那样运行。让我们看看它是否适用于 OP 的情况。 :) 这对我不起作用。 @Bozho:见上一句。我认为问题正如@BalusC 在他对我的问题的评论中所描述的那样。 好奇你所说的“对我不起作用”是什么意思,因为我们已经在生产环境中运行了几个月的代码。 我的意思是:&lt;c:if test="#!empty message"&gt;&lt;f:facet name="footer"&gt;#message&lt;/f:facet&gt;&lt;/c:if&gt; 没有在#message 为空时省略页脚。我不是在编写复合组件,所以这可能是问题的一部分。 它确实只在复合组件或标签文件中有用,因为它们基本上每次都被每个声明的标签实例化/执行一次。但是,在正常视图中,您依赖于更多因素:例如,当 EL 依赖于某些 JSF UIData/repeated 变量时,JSTL 不会像预期的那样运行,因为此信息在视图构建期间不可用。【参考方案2】:

我可以通过将facet 换成attribute 来解决这个问题。总结一下:

这行得通

<p:panel ...>
    <f:attribute name="footer" value="#message"/>
    <!-- ... -->
</p:panel>

但这不起作用

<p:panel footer="#message">
    <!-- ... -->
</p:panel>

这个也不行

<p:panel ...>
    <f:facet name="footer">#message</f:facet>
    <!-- ... -->
</p:panel>

也不是这个

<p:panel ...>
    <f:facet name="footer">
        <h:outputText value="#message" rendered="#!empty message"/>
    </f:facet>
    <!-- ... -->
</p:panel>

“作品”是指:

“当#message 为空或null 时,呈现no 页脚——不仅仅是一个空页脚;否则,使用指定的文本正确呈现页脚。”


PrimeFaces forum thread on this issue

【讨论】:

哦,有趣的一个。你是怎么发现的?幸运事故?挖了渲染器源? @BalusC: 反复试验 - 所以,当然,幸运的意外 :) 学习 JSF et al 无知有时是一种幸福。事实证明,构面实际上是作为属性存储的(优点是您可以在其中声明 UI 组件)。很高兴知道。 @BalusC:您是说构面只是可以包含其他 JSF 标记的属性?这是有道理的。这是 PrimeFaces 的事情,还是 JSF 范围内的事实? Facets 从一开始就在 JSF 中。例如。 &lt;h:dataTable&gt;&lt;f:facet name="footer"&gt;&lt;tfoot&gt;。但它们不作为属性存储在标准 JSF impl 中。我不确定 PrimeFaces 是如何做到的,因为我需要挖掘它的来源。【参考方案3】:

我在普通的 JSF 中遇到过类似的问题。我不确定&lt;p:panel&gt; 是如何呈现的,但如果它呈现为表格,你可以试试这个:

首先,像这样声明一个 CSS 类:

.HideFooter tfoot 
    display: none;

然后在面板上有条件地设置该类:

<p:panel styleClass="#renderFooterCondition ? null : 'HideFooter'">

页脚仍以 JSF 方式呈现,但在用户代理查看时不显示且不占用页面中的任何空间。

【讨论】:

【参考方案4】:

您可以声明一个 ui:param 并让模板在渲染时检查参数。

然后可以将模板中的构面声明为:

<f:facet name="#hideFooter == null or not hideFooter ? 'footer' : ''">
     #message
</f:facet>

然后任何页面都可以声明这个参数

<ui:param name='hideFooter' value='#some rule' />

并为参数设置适当的规则。对于任何没有声明参数的页面,都会显示页脚。

【讨论】:

【参考方案5】:

为什么不将页脚的内容封装到具有 render 属性的 panelGroup 中?

这边:

<p:panel header="some text">
    <f:facet name="footer">
    <h:panelGroup rendered="#!empty message">
        #message
    </h:panelGroup>
    </f:facet>
    <!-- ... -->
</p:panel>

我在我的 weapp 中执行此操作,它可以正常工作,没有渲染页脚。

虽然我不使用 primefaces,但我使用 h:datatable 使用它,但我认为它也必须使用 p:panel。

【讨论】:

【参考方案6】:

我使用 ui:fragment 成功解决了这个问题

<ui:fragment rendered="...Test...">
<f:facet name="footer">
...
</f:facet>
</ui:fragment>

例如可以有条件地渲染 primefaces 数据表的页脚(该 facet 的渲染属性不起作用)。

【讨论】:

在 p:dataTable (Primefaces 5.3) 的选定 p:column 中的 &lt;f:facet name="footer"&gt; 中为我工作。 编辑:撤销我的 +1。在选定的 p:dataTable 的 p:column 中 &lt;f:facet name="footer"&gt; 对我不起作用(Primefaces 5.3)。起初我以为是这样,但这只是针对“不渲染”的情况;我在进一步测试后发现它在所有情况下都会停止页脚刻面渲染。 嗯,是的,我只打算条件渲染。你还有什么期待?【参考方案7】:

不确定这对您的页脚效果如何,但我在尝试有条件地渲染图例时遇到了同样的问题。我通过在 facet 标记内的任何内容上使用渲染来修复它。

<p:fieldset>
<f:facet name="legend">
    <h:outputText value="#header1" rendered="#header1.exists"/>
    <h:outputText value="#header2" rendered="#not header1.exists"/>
</f:facet>
content
</p:fieldset>

我在使用 ui:repeat 尝试 c:if 时遇到了困难,所以这是我的解决方案。与您的问题不太一样,但类似。

【讨论】:

这个特殊的例子可以由&lt;p:fieldset legend="#header1.exists ? header1 : header2"&gt;完成。【参考方案8】:

Facets 不打算呈现 HTML,这就是它没有 render 属性的原因。构面将功能添加到页面。术语方面可能是一个糟糕的名称选择。这很模棱两可。

..如果 ITworld 的 Phil Johnson 编制的列表是正确的,那么 开发人员最难做的事情就是name things。

即。

JSF facets

项目构面是一个特定的功能单元,您可以在需要该功能时将其添加到项目中。将项目方面添加到项目时,它可以根据特定项目的特征向项目添加性质、构建器、类路径条目和资源。 JSF facets 定义了启用 JSF 的 Web 应用程序的特征。 JSF facets 指定适用于您的 JSF 项目的要求和约束。

JSF facets 为您的 Web 应用程序提供一组行为和功能。

【讨论】:

【参考方案9】:

我尝试了这个解决方案,没问题。 (http://www.coderanch.com/t/431222/JSF/java/dynamically-set-panel-header-condition)

<rich:dataGrid value="#myMB.student.list" rendered="#!empty myMB.student and !empty myMB.student.list" var="st" rowKeyVar="row">
    <rich:panel>                                            
        <f:facet name="header">
        <h:panelGroup id="panelHeader">
            <h:outputText value="Just one student" id="header1" required="true" rendered="#!myMB.manyStudents"/>
            <h:outputText value="#row+1º Student"  id="header2" required="true"  rendered="#myMB.manyStudents"/>
            </h:panelGroup>                                 
        </f:facet>
<rich:panel>

【讨论】:

【参考方案10】:

这是对 Ludovic Pénet 答案的反驳。

这在 &lt;f:facet name="footer"&gt; 中对我有用,在 p:dataTable (Primefaces 5.3) 的选定 p:column 项目中:

...

注意ui:fragmentf:facet 内部,而不是在外部(不包装)它。当每个页脚方面都经过测试以不呈现时,它肯定会完全删除整行(据我所知,与ui:fragment 中的内容无关)。

【讨论】:

【参考方案11】:

试试这个,来自 primefaces 网页

<p:columnGroup type="footer">
    <p:row>
        <p:column colspan="3" style="text-align:right" footerText="Totals:" />
        <p:column footerText="your value in ajax" />

        <p:column footerText="your value in ajax" />
    </p:row>
</p:columnGroup>

点击here,查看primefaces的网页

【讨论】:

【参考方案12】:

对于那些试图隐藏 footer 而不是 header,但语法 component.facets.footer 不起作用的人,应该试试这个:

<p:panel id="panelContent">
    <c:if test="#not empty cc.facets.footer">
        <f:facet name="footer" >
           your content
        </f:facet>
    </c:if>
</panel>

【讨论】:

以上是关于如何有条件地渲染 <f:facet>?的主要内容,如果未能解决你的问题,请参考以下文章

[react] 怎样有条件地渲染组件?

用XSLT替换f:facet属性

有条件地渲染同一个组件不会触发挂载()钩子。

React - 有条件地渲染多个元素

当有条件地渲染两个组件时,每个组件都包含一个 react-native-elements <Input>,激活一个会导致组件异常/不渲染

如何使用 clsx 有条件地渲染 css?