2012-08-16 13 views
8

tengo el siguiente construir en varios lugares en mi aplicación web con el fin de hacer que condicionalmente fragmentos de página en función de algunas acciones:Omitir la ejecución de <ui:include> cuando el componente de interfaz de usuario de los padres no se representa

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

he observado, que el <ui:include> todavía se ejecuta incluso cuando el atributo rendered evalúa false. Esto crea innecesariamente todos los beans de respaldo asociados con el archivo service1.xhtml que se incluye.

¿Cómo puedo omitir la ejecución de <ui:include> cuando el componente de IU principal no se procesa, de modo que todos los beans de respaldo no se creen innecesariamente?

Respuesta

9

Lamentablemente, esto es por diseño. El <ui:include> se ejecuta como un gestor de etiquetas durante el tiempo de compilación de la vista, mientras que el atributo rendered se evalúa durante el tiempo de visualización de la vista. Esto puede entenderse mejor mediante la lectura cuidadosamente esta respuesta y sustituyendo "JSTL" con "<ui:include>": JSTL in JSF2 Facelets... makes sense?

Hay varias maneras de resolver este, dependiendo del requerimiento funcional concreta:

  1. utilizar una vista construya la etiqueta del tiempo como <c:if> en vez de <h:panelGroup>. Esto sin embargo pone implicaciones en el #{managedBean}. No se puede ver en el ámbito y debe hacer su trabajo según los parámetros de solicitud HTTP. Exactamente esos parámetros de solicitud HTTP también deben conservarse en la solicitud posterior (por ejemplo, <f:param>, includeViewParams, etc.) para que no se rompa cuando se restaura la vista.

  2. Reemplazar <ui:include> por una costumbre UIComponent que invoca FaceletContext#includeFacelet() durante el método UIComponent#encodechildren(). Hasta el momento, no existe tal componente en ninguna de las bibliotecas existentes. Pero puedo decir que ya lo tengo en mente como una adición futura para OmniFaces y funciona como se espera intuitivamente aquí en mi entorno de prueba (con Mojarra). He aquí un ejemplo patada de salida:

    @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

Hola, gracias por BaluSC respuesta. Pero no puedo entender la respuesta. Donde necesitamos declarar este componente y cómo usarlo. –

+0

Hola Balusc, después de agregar el componente, la omisión de include está sucediendo perfectamente. Pero cuando se requiere que se incluya, ese tiempo falla. Pegaré la excepción FYI. –

+0

¿Ya se ha incluido esto en omnifaces, BalusC? –

6

Uso expresión condicional como ui: include src:

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