2012-08-16 10 views
8

Ho la seguente costruire in diversi luoghi nella mia webapp per rendere condizionale frammenti di pagina a seconda alcune azioni:Ignora l'esecuzione <ui:include> quando componente principale interfaccia utente non è resa

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

ho osservato, che la <ui:include> è ancora eseguito anche se l'attributo rendered valuta false. Ciò crea inutilmente tutti i bean di supporto associati al file service1.xhtml che è stato incluso.

Come è possibile saltare l'esecuzione di <ui:include> quando il componente dell'interfaccia utente padre non viene eseguito il rendering, in modo che tutti questi bean di supporto non vengano creati inutilmente?

risposta

9

Sfortunatamente, questo è di progettazione. <ui:include> viene eseguito come taghandler durante il tempo di creazione della vista, mentre l'attributo rendered viene valutato durante il tempo di rendering della vista. Questo può essere meglio compresa leggendo attentamente questa risposta e sostituendo "JSTL" con "<ui:include>": JSTL in JSF2 Facelets... makes sense?

Ci sono diversi modi per risolvere questo, a seconda del requisito funzionale concreto:

  1. Usa una vista creare un tag temporale come <c:if> anziché <h:panelGroup>. Ciò tuttavia pone implicazioni nello #{managedBean}. Non può essere considerato con scope e dovrebbe fare il suo lavoro in base ai parametri di richiesta HTTP. Esattamente quei parametri di richiesta HTTP dovrebbero anche essere conservati nella richiesta successiva (ad esempio, <f:param>, includeViewParams, ecc.) In modo che non si interrompa quando viene ripristinata la vista.

  2. Sostituire <ui:include> da una consuetudine UIComponent che invoca FaceletContext#includeFacelet() durante il metodo UIComponent#encodechildren(). Finora nessun componente di questo tipo esiste in nessuna delle librerie esistenti. Ma posso dire che ho già pensato a questo come aggiunta futura per OmniFaces e funziona intuitivamente come previsto qui nel mio ambiente di test (con Mojarra). Ecco un esempio kickoff:

    @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

Ciao, grazie per la risposta BaluSC. Ma Iam non è in grado di capire la risposta. Dove dobbiamo dichiarare questo componente e come usarlo. –

+0

Ciao Balusc, dopo aver aggiunto il componente, il salto di inclusione sta avvenendo perfettamente. Ma quando è richiesto di essere incluso, quel tempo non funziona. Incollerò l'eccezione FYI. –

+0

Questo è già stato incluso in omnifaces, BalusC? –

6

Usa espressione condizionale come ui: includono src:

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