如何有条件地渲染 <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 在他对我的问题的评论中所描述的那样。
好奇你所说的“对我不起作用”是什么意思,因为我们已经在生产环境中运行了几个月的代码。
我的意思是:<c:if test="#!empty message"><f:facet name="footer">#message</f:facet></c:if>
没有在#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 中。例如。<h:dataTable><f:facet name="footer">
为 <tfoot>
。但它们不作为属性存储在标准 JSF impl 中。我不确定 PrimeFaces 是如何做到的,因为我需要挖掘它的来源。【参考方案3】:
我在普通的 JSF 中遇到过类似的问题。我不确定<p:panel>
是如何呈现的,但如果它呈现为表格,你可以试试这个:
首先,像这样声明一个 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 中的<f:facet name="footer">
中为我工作。
编辑:撤销我的 +1。在选定的 p:dataTable 的 p:column 中 <f:facet name="footer">
对我不起作用(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 时遇到了困难,所以这是我的解决方案。与您的问题不太一样,但类似。
【讨论】:
这个特殊的例子可以由<p:fieldset legend="#header1.exists ? header1 : header2">
完成。【参考方案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 答案的反驳。
这在 <f:facet name="footer">
中对我有用,在 p:dataTable (Primefaces 5.3) 的选定 p:column
项目中:
...
注意ui:fragment
在f: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-native-elements <Input>,激活一个会导致组件异常/不渲染