有条件地渲染一个 <ui:include>

Posted

技术标签:

【中文标题】有条件地渲染一个 <ui:include>【英文标题】:Conditionally rendering an <ui:include> 【发布时间】:2013-09-13 06:21:38 【问题描述】:

我正在尝试切换显示&lt;rich:dataTable&gt; 的页面。在我只包含&lt;ui:include&gt; 模板之前,它只会一直显示表格。

<ui:include src="../log/viewDlg.xhtml"/>

现在我希望能够在网页上打开/关闭它。在页面上显示可能带有按钮或链接。我怎样才能实现它?


更新 1:由于某种奇怪的原因,我无法让它显示出来,这是我目前根据反馈写的内容

查看:

<a4j:commandLink value="View"
    action="#bean.showview" render="viewPanel"/>

<h:panelGroup id="viewPanel">
    <h:panelGroup id="tableRenderPanel" rendered="#bean.showPolicyView">    
        <ui:include src="../log/viewDlg.xhtml"/>
    </h:panelGroup>                         
</h:panelGroup>

支持 bean:

private boolean showPolicyView = false;

public void showView() 
    showPolicyView = !showPolicyView;


public boolean isShowPolicyView()
    return showPolicyView;

【问题讨论】:

【参考方案1】:

我更喜欢使用ui:include,而不是像这里插入h:panelBoxes

<ui:fragment rendered="#myBean.yourCondition()">
    <ui:include src="viewA.xhtml"/>
</ui:fragment>
<ui:fragment rendered="#not myBean.yourCondition()">
    <ui:include src="viewB.xhtml"/>
</ui:fragment>

优点:标签处理程序不代表组件,并且一旦构建视图就永远不会成为组件树的一部分。它不会干扰您的 CSS - 相反,h:panelBox 会插入 div 或 span。


...另一种方法是 c:choose,它可以工作,但会导致渲染阶段问题。

<c:choose>
    <c:when test="#myBean.yourCondition()">
        <ui:include src="viewA.xhtml"/>
    </c:when>
    <c:otherwise>
        <ui:include src="viewB.xhtml"/>
    </c:otherwise>
</c:choose>

警告:在使用标签处理程序(如任何c:xxx)时,请务必了解difference between UI Components and Tag Handlers。即 UI 组件和标签处理程序在不同阶段渲染。这意味着您不能在复合组件中创建变量并在嵌套标记处理程序中使用它。 c:chooseui:include 都是标签处理程序,所以通常这不是问题。阅读链接,这是一个非常简短且非常有见地的示例。

【讨论】:

【参考方案2】:

&lt;ui:include&gt; 包裹在两个&lt;h:panelGroup&gt; 元素中。这里有个问题,你不能重新渲染一个条件组件。这是为什么?因为当元素的rendered 属性解析为false 时,在渲染视图时不会考虑它,因此它不能成为操作的目标(在这种情况下,与渲染有关)。

跳转到代码,你会得到这个:

<h:panelGroup id="wrapperPanel">
    <h:panelGroup id="tableRenderPanel" rendered="#yourBean.renderTable">
        <ui:include src="../log/viewDlg.xhtml"/>
    </h:panelGroup>
</h:panelGroup>

yourBean#renderTable 是一个Boolean 属性,用于确定是否将呈现组件。当计算结果为false 时,该组件不包含在组件树中。


切换视图

要切换视图,只需创建一个刷新页面的 bean 方法

<h:commandLink action="#yourBean.toggleTableView"/>

或通过 AJAX 的特定面板。要在 JSF 1.2 中做到这一点,如果可以的话,请依靠 RichFaces 之类的扩展来引入 AJAX。例如,如果您选择 RichFaces,您可以使用 &lt;a4j:commandLink/&gt; 及其方便的 render(或旧版本中的 reRender)属性来实现在 JSF 2 中使用 &lt;f:ajax/&gt; 可以正常执行的操作

<a4j:commandLink action="#yourBean.toggleTableView" reRender="wrapperPannel"/>

或者,另一种选择是

<a4j:commandLink action="#yourBean.toggleTableView">
    <a4j:support event="oncomplete" reRender="wrapperPannel"/>
</a4j:commandLink>

请注意,reRender 属性可能会根据您的页面结构而有所不同,但它应该始终引用最后包装面板的 id。此外,在 RichFaces 的后期版本中,reRender 被简单地重命名为 render

所以,假设您在yourBean 中有一个renderTable 属性(getter + setter),toggleTableView 必须更改它,以便动态定义是否要渲染组件(renderTable = false) .


RichFaces 简介

查看this link 以获取在您的项目中设置 RichFaces 的帮助。

【讨论】:

@GilbertV 哦,我明白了,我很傻。 f:ajax 稍后介绍。如果可以,请在与 JSF 1.2 兼容的版本中使用诸如 RichFaces 或 PrimeFaces 之类的 JSF 扩展。这些为以前的 JSF 版本添加了很好的 AJAX 提升。我将更新我的答案以使其 1.2 友好。 @GilbertV 这里有些奇怪,h:commandLink 没有render 属性。如果您再次检查答案,会有一个非常小的区别:它是 a4j:commandLink 而不是 h:commandLinka4j 属于 RichFaces。 @GilbertV 单击链接时,您是否收到任何有关未找到 id 的错误? @GilbertV 我添加了一个新选项,它使用来自早期版本 RichFaces 的旧 a4j:support 元素。如果你有,试试看。此外,wrapperPanel 可以从 h:panelGroup 更改为 a4j:outputPanel @GilbertV 支持指令与特定事件相关联。在这种情况下,请尝试event="oncomplete"

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

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

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

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

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

将组件保存到列表中,然后有条件地渲染

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