跳过执行< ui:include>何时不呈现父UI组件 [英] Skip executing <ui:include> when parent UI component is not rendered

查看:145
本文介绍了跳过执行< ui:include>何时不呈现父UI组件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在webapp中的几个地方有以下构造,以便根据某些操作有条件地呈现页面片段:

I have the following construct at several places in my webapp in order to conditionally render page fragments depending on some actions:

<h:panelGroup rendered="#{managedBean.serviceSelected == 'insurance'}">
    <ui:include src="/pages/edocket/include/service1.xhtml" />
</h:panelGroup>

我观察到< ui:include> 呈现的属性评估 false ,c $ c>仍然执行。这会不必要地创建与 service1.xhtml 文件关联的所有支持bean。

I have observed, that the <ui:include> is still executed even when the rendered attribute evaluates false. This unnecessarily creates all backing beans associated with the service1.xhtml file which is been included.

如何跳过在未呈现父UI组件时执行< ui:include> ,以便不会不必要地创建所有这些支持bean?

How can I skip executing the <ui:include> when the parent UI component is not rendered, so that all those backing beans are not unnecessarily created?

推荐答案

不幸的是,这是设计的。 < ui:include> 在视图构建期间作为标记处理程序运行,而呈现的属性将被评估在视图渲染时间。通过仔细阅读这个答案并用< ui:include> 代替JSTL可以更好地理解这一点: JSF2 Facelets中的JSTL ......有意义吗?

Unfortunately, this is by design. The <ui:include> runs as being a taghandler during the view build time, while the rendered attribute is evaluated during the view render time. This can be better understood by carefully reading this answer and substituting "JSTL" with "<ui:include>": JSTL in JSF2 Facelets... makes sense?

有几个解决方法,具体取决于具体的功能要求:

There are several ways to solve this, depending on the concrete functional requirement:


  1. 使用视图构建时标记,如 < c:if> 而不是< h:panelGroup> 。但是这会对#{managedBean} 产生影响。它不能是视图范围,应该根据HTTP请求参数完成其工作。确切地说,那些HTTP请求参数也应保留在后续请求中(例如< f:param> includeViewParams ,等等,以便在视图恢复时不会中断。

  1. Use a view build time tag like <c:if> instead of <h:panelGroup>. This however puts implications into the #{managedBean}. It can't be view scoped and should do its job based on HTTP request parameters. Exactly those HTTP request parameters should also be retained in subsequent request (by e.g. <f:param>, includeViewParams, etc) so that it doesn't break when the view is restored.

替换< ui:include> 由自定义 UIComponent ,它调用 FaceletContext #includeFacelet() =http://docs.oracle.com/javaee/6/api/javax/faces/component/UIComponent.html#encodeChildren%28javax.faces.context.FacesContext%29 =nofollow noreferrer> UIComponent #cditchildren() 方法。到目前为止,在任何现有库中都不存在这样的组件。但我可以说,我已经考虑过这样一个作为 OmniFaces 的未来添加内容,它在这里可以直观地预期在我的测试环境中(使用Mojarra)。这是一个启动示例:

Replace <ui:include> by a custom UIComponent which invokes FaceletContext#includeFacelet() during the UIComponent#encodechildren() method. So far no such component exist in any of the existing libraries. But I can tell that I've already such one in mind as a future addition for OmniFaces and it works as intuitively expected here at my test environment (with Mojarra). Here's a kickoff example:

@FacesComponent(Include.COMPONENT_TYPE)
public class Include extends UIComponentBase {

    public static final String COMPONENT_TYPE = "com.example.Include";
    public static final String COMPONENT_FAMILY = "com.example.Output";

    private enum PropertyKeys {
        src;
    }

    @Override
    public String getFamily() {
        return COMPONENT_FAMILY;
    }

    @Override
    public boolean getRendersChildren() {
        return true;
    }

    @Override
    public void encodeChildren(FacesContext context) throws IOException {
        getChildren().clear();
        FaceletContext faceletContext = ((FaceletContext) context.getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY));
        faceletContext.includeFacelet(this, getSrc());
        super.encodeChildren(context);
    }

    public String getSrc() {
        return (String) getStateHelper().eval(PropertyKeys.src);
    }

    public void setSrc(String src) {
        getStateHelper().put(PropertyKeys.src, src);
    }

}


这篇关于跳过执行&lt; ui:include&gt;何时不呈现父UI组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆