当未呈现父UI组件时,跳过执行<ui:include>

Har*_*012 8 facelets include jsf-2

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

<h:panelGroup rendered="#{managedBean.serviceSelected == 'insurance'}">
    <ui:include src="/pages/edocket/include/service1.xhtml" />
</h:panelGroup>
Run Code Online (Sandbox Code Playgroud)

我观察到,<ui:include>即使rendered属性评估,仍然会执行false.这会不必要地创建与包含的service1.xhtml文件关联的所有后备bean .

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

Bal*_*usC 9

不幸的是,这是设计的.的<ui:include>运行为在视图生成时一taghandler,而rendered属性视图期间评估渲染时间.通过仔细阅读这个答案并用""替换"JSTL"可以更好地理解这一点<ui:include>:JSF2 Facelets中的JSTL ......有意义吗?

根据具体的功能要求,有几种方法可以解决这个问题:

  1. 使用视图构建时标记<c:if>代替<h:panelGroup>.然而,这会产生影响#{managedBean}.它不能是视图范围,应该根据HTTP请求参数完成其工作.恰好那些HTTP请求参数也应在后续请求被保留(通过例如<f:param>,includeViewParams等),以便恢复视图时它不会破裂.

  2. 替换<ui:include>为在方法期间UIComponent调用的自定义.到目前为止,在任何现有库中都不存在这样的组件.但我可以说,我已经将这样的想法作为OmniFaces的未来添加,并且它在我的测试环境(使用Mojarra)中可以直观地预期.这是一个启动示例:FaceletContext#includeFacelet()UIComponent#encodechildren()

    @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);
        }
    
    }
    
    Run Code Online (Sandbox Code Playgroud)


Nei*_*ens 6

使用条件表达式作为ui:include src:

<h:panelGroup>
    <ui:include 
        src="#{managedBean.serviceSelected == 'insurance' ?
            '/pages/edocket/include/service1.xhtml'
            :
            '/pages/empty.xhtml'}"
    />
</h:panelGroup>
Run Code Online (Sandbox Code Playgroud)