2012-08-16 41 views
8

我有以下的,以有条件地呈现页面片段根据一些动作在我的webapp的几个地方建设:跳过执行<ui:include>当父UI组件未呈现

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

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

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

回答

9

不幸的是,这是设计。 <ui:include>在视图生成时间内作为标记处理程序运行,而rendered属性在视图生成时间内计算。这可以通过仔细阅读这个答案而代以“JSTL”与“<ui:include>”得到更好的理解:JSTL in JSF2 Facelets... makes sense?

有几种方法来解决这个问题,这取决于具体的功能要求:

  1. 使用视图建立时间标记,如<c:if>而不是<h:panelGroup>。然而这会影响到#{managedBean}。它不能被视为范围,并且应该根据HTTP请求参数来完成它的工作。恰好那些HTTP请求参数也应该保留在随后的请求中(例如通过<f:param>,includeViewParams等),以便它在恢复视图时不会中断。

  2. 用定制UIComponent替换<ui:include>,在UIComponent#encodechildren()方法中调用FaceletContext#includeFacelet()。到目前为止,在任何现有的库中都不存在这样的组件。但是我可以告诉我,我已经将这样一个想法作为OmniFaces的未来增加,并且在我的测试环境(与Mojarra一起)中可以直观地发挥作用。这里有一个开球例如:

    @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); 
        } 
    
    } 
    
+0

嗨,感谢您的回复BaluSC。但Iam无法理解答案。我们需要声明这个组件以及如何使用它。 – 2012-08-17 05:10:14

+0

嗨Balusc,添加组件后,包含的跳过正在发生完美。但是,如果需要纳入,那么时间就会失败。我将粘贴异常FYI。 – 2012-08-22 08:02:40

+0

这个已经包含在omnifaces中了吗,BalusC? – 2013-01-28 08:50:13

6

使用条件表达式为UI:包括源:

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