有条件地渲染<ui:include>元素

18

我想切换显示一个包含<rich:dataTable>的页面。之前我只需要包含<ui:include>模板,它就一直显示整个表格。

<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;
}
2个回答

21

<ui:include>标签包装在两个<h:panelGroup>元素中。这里有一个注意点,你不能重新渲染一个条件组件。为什么呢?因为当元素的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}"/>

如果您使用JSF 1.2,想要通过AJAX加载特定面板,则需要依赖类似RichFaces的扩展来引入AJAX。举个例子,如果您选择使用RichFaces,可以使用<a4j:commandLink/>及其方便的render属性(在旧版本中为reRender),即可实现在JSF 2中使用<f:ajax/>正常实现的功能。

<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

请查看此链接,以获取有关在项目中设置 RichFaces 的帮助。

1
@GilbertV 哦,我明白了,我真是太傻了。f:ajax是后来引入的。如果可以的话,使用JSF扩展库,如RichFaces或PrimeFaces,并使用与JSF 1.2兼容的版本。这些库可以为之前的JSF版本添加很好的AJAX支持。我会更新我的答案,使其适用于1.2版本。 - Fritz
1
@GilbertV 那里有些奇怪,h:commandLink 没有 render 属性。如果你再检查一遍答案,会发现一个非常小的区别:它是一个 a4j:commandLink 而不是 h:commandLinka4j 属于 RichFaces。 - Fritz
1
@GilbertV 我添加了一个新选项,使用早期版本的RichFaces中的旧a4j:support元素。如果您有它,请尝试一下。此外,wrapperPanel可以从h:panelGroup更改为a4j:outputPanel - Fritz
1
@GilbertV 支持指令与特定事件相关联。在这种情况下,请尝试使用 event="oncomplete" - Fritz
1
@GilbertV 你的bean是RequestScoped吗?如果是,由于默认值为false,将其设置为true最终不会有帮助,因为一个新的bean被创建来处理请求。一切都正常,除了结果不足以使用。 - Fritz
显示剩余21条评论

5

我更喜欢使用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)时,请确保了解UI组件和标签处理程序之间的区别。即UI组件和标签处理程序在不同的阶段呈现。这意味着您不能在复合组件中创建一个变量并在嵌套的标签处理程序中使用它。c:chooseui:include都是标签处理程序,因此通常不会出现问题。阅读链接,这是一个非常简短而深入的例子。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接