Cómo ajax-refresh dynamic incluir contenido por menú de navegación? (JSF SPA)


Estoy aprendiendo JSF 2 gracias a este sitio había aprendido mucho en tan poco tiempo.

Mi pregunta es sobre cómo implementar un diseño común para todas mis páginas de JSF 2 y hacer que solo la parte de contenido de la página refresque no toda la página cada vez que haga clic en un enlace/menú de un panel diferente. Estoy usando el enfoque Facelets hace lo que quiero, excepto que cada vez que hago clic en un enlace de un panel (por ejemplo, elementos de menú del panel izquierdo) toda la página se actualiza. Lo que estoy buscando for es una forma de actualizar solo la parte de contenido de mi página. Para ilustrar esto a continuación es mi destino pagelayout.

introduzca la descripción de la imagen aquíNo publiqué mi código porque no estoy seguro de si las Facelets pueden hacer esto . ¿Hay otro enfoque más adecuado para mis necesidades que no sean las facetas?

Author: BalusC, 2011-08-18

3 answers

Un enfoque sencillo sería el siguiente punto de vista:

<h:panelGroup id="header" layout="block">
    <h1>Header</h1>
</h:panelGroup>
<h:panelGroup id="menu" layout="block">
    <h:form>
        <f:ajax render=":content">
            <ul>
                <li><h:commandLink value="include1" action="#{bean.setPage('include1')}" /></li>            
                <li><h:commandLink value="include2" action="#{bean.setPage('include2')}" /></li>            
                <li><h:commandLink value="include3" action="#{bean.setPage('include3')}" /></li>            
            </ul>
        </f:ajax>
    </h:form>
</h:panelGroup>
<h:panelGroup id="content" layout="block">
    <ui:include src="/WEB-INF/includes/#{bean.page}.xhtml" />
</h:panelGroup>

Con este frijol:

@ManagedBean
@ViewScoped
public class Bean implements Serializable {

     private String page;

     @PostConstruct
     public void init() {
         page = "include1"; //  Default include.
     }

     // +getter+setter.
 }

En este ejemplo, las plantillas de inclusión reales son include1.xhtml, include2.xhtml y include3.xhtml en la carpeta /WEB-INF/includes (la carpeta y la ubicación son completamente libres a su elección; los archivos solo se colocan en /WEB-INF para evitar el acceso directo adivinando la URL en la barra de direcciones del navegador).

Este enfoque funciona en todas las versiones de MyFaces, pero requiere un mínimo de Mojarra 2.3.0. En caso de estás usando una versión de Mojarra anterior a la 2.3.0, entonces todo esto falla cuando la página <ui:include> a su vez contiene un <h:form>. Cualquier postback fallará porque le falta totalmente el estado de vista. Puede resolver esto actualizando a mínimamente Mojarra 2.3.0 o con un script que se encuentra en esta respuesta h:commandButton/h:commandLink no funciona en el primer clic, solo funciona en el segundo clic, o si ya está utilizando la biblioteca de utilidades JSF OmniFaces, use su script FixViewState. O, si ya está utilizando PrimeFaces y utiliza exclusivamente <p:xxx> ajax, entonces ya se tiene en cuenta de forma transparente.

También, asegúrese de que está utilizando mínimamente Mojarra 2.1.18 ya que las versiones anteriores fallarán en mantener vivo el bean con el alcance de la vista, causando que el mal include se use durante el postback. Si no puede actualizar, entonces tendría que recurrir al enfoque de abajo (relativamente torpe) de representar condicionalmente la vista en lugar de construir condicionalmente la vista:

...
<h:panelGroup id="content" layout="block">
    <ui:fragment rendered="#{bean.page eq 'include1'}">
        <ui:include src="include1.xhtml" />
    </ui:fragment>
    <ui:fragment rendered="#{bean.page eq 'include2'}">
        <ui:include src="include2.xhtml" />
    </ui:fragment>
    <ui:fragment rendered="#{bean.page eq 'include3'}">
        <ui:include src="include3.xhtml" />
    </ui:fragment>
</h:panelGroup>

La desventaja es que la vista se volvería relativamente grande y que todos los frijoles administrados asociados podrían inicializarse innecesariamente, aunque no se usarían según la condición renderizada.

En cuanto al posicionamiento de los elementos, eso es solo cuestión de aplicar el CSS correcto. Eso está más allá del alcance de JSF :) Al menos, <h:panelGroup layout="block"> hace un <div>, por lo que debería ser suficiente.

Por último, pero no menos importante, este SPA (Aplicación de una sola página) el enfoque no es amigable con el SEO. Todas las páginas no son indexables por los bots de búsqueda ni marcables por los usuarios finales, es posible que deba jugar con el historial de HTML5 en el cliente y proporcionar un respaldo del lado del servidor. Además, en el caso de las páginas con formularios, la misma instancia de bean con ámbito de vista se reutilizará en todas las páginas, lo que resultará en un comportamiento de alcance poco intuitivo cuando navegue de vuelta a una página visitada anteriormente. Yo sugeriría ir con el enfoque de plantillas en su lugar como se describe en la 2a parte de este respuesta: ¿Cómo incluir otro XHTML en XHTML usando Facelets JSF 2.0?Véase también ¿Cómo navegar en JSF? Cómo hacer que la URL refleje la página actual (y no la anterior).

 58
Author: BalusC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-13 06:44:08

Si solo desea actualizar parte de la página, solo hay 2 formas de hacerlo (para la web en general, no solo para JSF). Tienes que usar marcos o Ajax. JSF 2 soporta ajax de forma nativa, echa un vistazo a la etiqueta f: ajax para actualizar solo 1 componente sin recargar toda la página.

 2
Author: GBa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-18 14:14:01

Netbeans proporciona un asistente que crea el diseño propuesto con un esfuerzo mínimo utilizando JSF. Por lo tanto, la mejor manera de comenzar es echar un vistazo a Facelets Template Wizard y mirar la fuente generada.

 0
Author: lu4242,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-18 19:01:20