2012-08-16 42 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>