« Terug

RichFaces, trabajando con tablas (3): ordenación y filtrado manuales

Este artículo se plantea como continuación de "RichFaces, trabajando con tablas (2)". Describe los pasos a seguir para incorporar mecanismos de ordenación y filtrado dentro de tablas paginadas que siguen el modelo descrito en el post anterior.

Introducción

El uso de los atributos sortBy y filterBy del componente rich:column NO será válido cuando se trabaja con modelos de datos complejos como el que se presentó en el artículo "RichFaces, trabajando con tablas (2)". Se deben implementar mecanismos de ordenación y filtrado manuales que sean capaces de manejar este modelo paginado.

Se van a definir commandLinks dentro de las columnas de la tabla que van a lanzar peticiones Ajax para modificar el orden en el que se muestran los datos dentro del dataTable.

Se van a crear inputText para definir mecanismos de filtrado.

Ordenación manual

Modificaciones en la vista

Para aplicar ordenación sobre una estructura de datos compleja se debe modificar la renderización. Se incorpora una nueva acción dentro de la faceta de cabecera que pasa como parámetro, en la petición que genera, el campo a partir del cuál se va a ordenar.

Por ejemplo, si se hace click sobre la columna Código de factura se enviará un parámetro llamado sortField cuyo valor será codfactura y cuando se genere la respuesta se re-renderizará la tabla paginada:

<h:column>
 <f:facet name="header">
    <a4j:commandLink value="Código de factura" reRender="tabla">
       <a4j:actionparam name="sortField" value="codfactura" />
    </a4j:commandLink>
 </f:facet>
 <h:outputText value="#{f.codfactura}"></h:outputText>
</h:column>

 

¿En este caso se deben utilizar atributos para optimizar el envío de información? ¿ajaxSingle = “true”? No, la petición desencadenada por esta acción debe enviar la información de la tabla para poder procesarla mediante el ciclo de vida estándar.

¿Algún tipo de renderización adicional? Queremos que, una vez que el orden de los datos sea modificado, sólo sea re-renderizada la tabla. Los demás contenidos de la página deben quedar intactos.

Por esta razón, se utiliza en atributo reRender asociado a la tabla.

<rich:dataTable id="tablaFacturas" value="#{paginacion2.facturas}"
                var="f" rows="5" reRender="scroll01" width="100%">
  <rich:column id="concepto">
    <f:facet name="header">
      <h:outputText value="Concepto"></h:outputText>
    </f:facet>
    <a4j:commandLink id="accion" ajaxSingle="true" limitToList="true">
                     <h:outputText value="#{f.concepto}" />
    </a4j:commandLink>
  </rich:column>
  <rich:column>
    <f:facet name="header">
      <a4j:commandLink value="Código de factura" reRender="tablaFacturas">
        <a4j:actionparam name="sortField" value="codfactura" />
      </a4j:commandLink>
    </f:facet>
    <h:outputText value="#{f.codfactura}"></h:outputText>
  </rich:column>

El método update()

El modelo de datos propuesto en el artículo "RichFaces, trabajando con tablas (2)" incorpora un método llamado update() como responsable de todos los procesos de actualización del modelo. Este método se ejecuta, dentro del ciclo de vida JSF en la fase de actualización del modelo, como resultado de una acción dentro de la tabla que, evidentemente, tiene que enviar la tabla como parte de la información a procesar en el servidor. El caso que estamos analizando cumple todas esas condiciones. Por esta razón, este método nos va a permitir implementar el concepto de ordenación.

...
public void update() {
  // Codigo para cambiar el criterio de ordenación.
}
...

 

Se muestra a continuación código de ejemplo:

@Override
public void update() {    // Paso 1: Se comprueba si se aplica criterio de ordenación.
  if(getCriterioOrdenacion()!=null){
        // Paso 2: Se recupera al criterio de ordenación a aplicar.
        final String nuevoCriterio = getCriterioOrdenacion().toString(); 
        // Paso 3: Se comprueba si el criterio de ordenación es igual al que está activo.
        if(nuevoCriterio.equals(dataProvider.getOrdenacion())){
          // Paso 4: Si el criterio de ordenación es el mismo, debemos cambiar
          //         el orden.
          dataProvider.setDescendente(!dataProvider.isDescendente());
        }
        dataProvider.setOrdenacion(nuevoCriterio);
   }
   // El atributo detached indica si el modelo de datos está serializado o si hay
   // que volver a la base de datos a recuperar la información de nuevo.
   // En el caso de un cambio de ordenación, debemos lanzar una nueva consulta.
   detached = false;
}

Como se ha podido ver en el código, se crea y utiliza un método auxiliar llamado getCriterioOrdenacion para manejar el criterio de ordenación:

protected Object getCriterioOrdenacion(){
      // Paso 1: Se recupera el contexto JSF
     final FacesContext contexto = FacesContext.getCurrentInstance();
     // Paso 2: Se obtiene el parametro pasado en la petición.
     final Object o =
           contexto.getExternalContext().getRequestParameterMap().get("sortField");
     return o;
}

El método getItemsByRange del proveedor

Lógicamente, este método debe ser modificado para manejar el concepto de ordenación. Por ejemplo:

servicioContabilidad.findAllPaginandoOrdenando(inicio, tam, asc, propiedad);

Análisis del ciclo de vida

La primera vez que se quiere visualizar la página, el ciclo de vida (como ya hemos comentado anteriormente es más corto):

  • Fase de restauración de la vista.
  • Fase de renderización:
    • En esta fase se ejecutan los métodos del modelo de datos anteriormente descritos. En el caso del método walk(), como la variable detached está a falso, obligatoriamente accede a base de datos y recupera SÓLO los objetos que va a mostrar la tabla. El número de objetos cargados en memoria es mucho menor que en el primero caso.
    • Posteriormente, se ejecuta el método getSerializableModel() que devuelve el modelo serializado poniendo la variable detached a verdadero (esto provoca que cuando se hagan peticiones sobre la página -Postbacks- no se recupere el modelo de la base de datos, ya que se encuentra serializado).

Una vez que la página se renderiza, se muestra:

Al hacer click sobre el enlace Código de factura se genera una petición al servidor. En ese caso se desencadena un ciclo de vida completo:

  • La petición es de tipo POSTBACK, es decir, el modelo está serializado y la variable detached está a true, por lo tanto, aunque se ejecute el método walk() del modelo NO se lanzan consultas a la base de datos.
  • Cuando se llega a la fase de actualización se ejecuta el método update(). Éste cambia el criterio de ordenación y pone la variable detached a falso.
  • En la fase de renderización, como detached está a falso, cuando se ejecuta el método walk() se accede a la base de datos aplicando el criterio de ordenación seleccionado. Como en la vista el atributo reRender está asociado a la tabla, ésta vuelve a renderizarse con los nuevos valores.

Filtrado manual

Conceptualmente, este proceso es muy parecido al de ordenación. Se debe modificar la vista para incorporar un campo que actúe como filtro y, posteriormente, se debe modificar el modelo de datos que proporciona registros a la tabla para que cuando se active el filtro actúe en consecuencia.

Modificaciones en la vista

Se incorpora un campo de texto que genera peticiones AJAX para activar el proceso de filtrado:

...
<rich:column id="concepto">
  <f:facet name="header">
    <h:outputLabel value="Concepto" for="filtroConcepto"></h:outputLabel>
    <h:inputText id="filtroConcepto"                  
                 value="#{paginacion2.facturas.dataProvider.filtroConcepto}"                  
                 style="width:90px" >         
       <a4j:support event="onblur" reRender="tablaFacturas,scroll01"              
                    ajaxSingle="true" limitToList="true">         
       </a4j:support>     
    </h:inputText> 
  </f:facet>
  <h:outputText value="#{f.concepto}" />
</rich:column>
...

Modificaciones en el método getItemsByRange()

Se debe modificar este método para que sea capaz de manejar filtros:

...
 rango = servicioContabilidad.
         findAllPaginandoOrdenandoFiltrado(
           firstRow, 
           endRow, 
           !descendente, 
           ordenacion, 
           filtroConcepto);
...

El resultado de estas modificaciones generan la siguiente vista:

Si se escribe en el filtro se genera un filtrado:

Opmerkingen
Link naar je weblog URL:

comments powered by Disqus