Tabla Seleccionable Mediante Checkbox con Filas no Seleccionables

Vamos a mostrar como hacer una tabla seleccionable en el que hay filas que no pueden ser seleccionables, con paginación y sin el checkbox de Seleccionar Todas.

Creamos en la carpeta src/main/web-app/resources/js del módulo WEB el fichero tabla_seleccionable.js con el siguiente contenido:

function configuraSeleccionMultiple(tabla) {
    try {
        // Permite ocultar la casilla de selección total de la cabecera
        $("th[id$='"+ tabla + ":seleccionColumn']").children("div.ui-chkbox").hide();
 
        $("input[id$='disableSelect']").each(function() {
            // Permite comprobar si una fila es seleccionable
            if ($(this).val() === "true") {
                // Si no seleccionable, desactivamos el comportamiento por defecto
                var tdPadre = $(this).parent(),
                    checkBox = $(tdPadre).children("div.ui-chkbox"),
                    checkBoxChildren = $(checkBox).children("div.ui-chkbox-box"),
                    trPadre = $(tdPadre).parent("tr.ui-datatable-selectable");
 
                $(trPadre).removeClass("ui-datatable-selectable");
 
                $(checkBox).removeClass("ui-state-active");
                $(checkBox).addClass("ui-state-disabled");
 
                // Remove the event from the link
                checkBox.onclick = null;
 
                // Add a check in for the class disabled
                $(checkBox).click(function(e) { 
                    if ($(checkBox).hasClass('ui-state-disabled')) {
                        e.stopImmediatePropagation();
                        e.preventDefault();
                    }                
                });
 
                $(checkBox).onmouseover = null;
                $(checkBox).mouseover(function(e) {
                    if ($(checkBox).hasClass('ui-state-disabled')) {
                        e.stopImmediatePropagation();
                        e.preventDefault();
                    }
                });
 
                $(checkBoxChildren).addClass("ui-state-hover");
                checkBoxChildren.onmouseover = null;
                $(checkBoxChildren).mouseover(function(e) {                 
                    e.stopImmediatePropagation();
                    e.preventDefault();
                    $(checkBoxChildren).addClass("ui-state-hover");
                });
 
            }
        });
    } catch (e) {}
}

En la página, cargamos el fichero Javascript en la cabecera de la página, de la siguiente manera:

<ui:composition template="/layout/template.xhtml">
 
    <ui:define name="head">
 
	<h:outputScript library="js" name="tabla_seleccionable.js" />
 
	<script type="text/javascript">
	$(document).ready(function() {
	    configuraSeleccionMultiple("listaTable");
	});
	</script>
 
    </ui:define>
 
    ...
</ui:composition>

El Javascript, permite ocultar el checkbox de selección global y desactivar la selección de las filas. Para eso, tenemos que pasarle el id del componente JSF <p:dataTable>, en este ejemplo es listaTable.

Tenemos la siguiente definición del <p:dataTable> de PrimeFaces:

    <p:dataTable id="listaTable" var="lista" tableStyleClass="table" value="#{servicioPendientePagoBean.model}"
        paginator="true" rows="10" paginatorPosition="bottom" lazy="true"
        selection="#{servicioPendientePagoBean.listaServicioPendientePago}" rowKey="#{lista.idServicio}" 		                            
        rowSelectMode="checkbox">
 
        <f:facet name="header">#{messages['label.header.listaServiciosNoPagados']}</f:facet>
        <p:column headerText="#{messages['tabla.gepeto.fechaServicio']}" width="7%" style="align:center">
            <h:outputText value="#{lista.getFechaServicio()}"/>
        </p:column>
        <p:column headerText="#{messages['tabla.gepeto.centroServicio']}" width="25%">
            <h:outputText value="#{lista.getCentro()}"/>
        </p:column>
        <p:column headerText="#{messages['tabla.gepeto.descripcionServicio']}" width="20%">
            <h:outputText value="#{lista.getServicio()}"/>
        </p:column>
        <p:column headerText="#{messages['tabla.gepeto.turnoServicio']}" width="9%">
            <h:outputText value="#{lista.getTurno()}"/>
        </p:column>
        <p:column headerText="#{messages['tabla.gepeto.dni']}" width="7%">
            <h:outputText value="#{lista.getDni()}"/>
        </p:column>
        <p:column headerText="#{messages['tabla.gepeto.nombre']}" width="20%">
            <h:outputText value="#{serviciosBean.nombreAuxiliar(lista.getDni())}"/>
        </p:column>			        
        <p:column headerText="#{messages['tabla.gepeto.alertas']}" width="5%">
		<s:div rendered="#{(serviciosBean.isAlertaHoras(lista.getDni(),lista.getFechaServicio()) ||  serviciosBean.isAlertaTika(lista.getDni(),lista.getFechaServicio()))}" > 
 
<i class="fa fa-exclamation-triangle fa-lg" style="color:red;" title="#{serviciosBean.showAlerta(lista.getDni(), lista.getFechaServicio())}"/> 
		</s:div>
        </p:column>
	<p:column id="seleccionColumn" headerText="#{messages['tabla.gepeto.aPago']}" width="5%" 
		selectionMode="multiple">
 
		<input type="hidden" name="disableSelect" id="disableSelect" value="#{(serviciosBean.isAlertaHoras(lista.getDni(),lista.getFechaServicio()) || serviciosBean.isAlertaTika(lista.getDni(),lista.getFechaServicio()))}" /> 		    
	</p:column>
	<f:facet name="footer">
	    	<div class="clearfix">
		    <div class="pull-right">
		    	<p class="text-right text-muted">En total hay #{servicioPendientePagoBean.model.rowCount} servicios pendientes de envío a Pagos</p>
		    </div>
	    	</div>
	</f:facet>
	<p:ajax event="page" oncomplete="configuraSeleccionMultiple('listaTable');"/>
	<p:ajax event="rowUnselectCheckbox" listener="#{servicioPendientePagoBean.deselecionarFila}" global="false"/>
    </p:dataTable>

En la definición de la tabla tenemos las siguientes propiedades referentes a la selección de filas:

  • id es el id del componente JSF, en este caso el valor es listaTable.
  • selection donde se almacenan los elementos seleccionados, es un get/set.
  • rowKey es el valor que representa la clave, que permite diferenciar los elementos seleccionados.
  • rowSelectMode indica que la selección/deselección solo se puede realizar si se hace click en el checkbox. Deshabliitando la selección selección/deselección cuando se hace click en la cualquier parte de la fila.

Para determinar la posición de la selección en PrimeFaces, se siguen las siguientes condiciones:

  • Para la primera posición, no hace falta utilizar el componente <p:column>, se define todo desde el propio componente p:dataTable>.
  • Para en cualquier otra posición, se utiliza un componente <p:column>.

En el ejemplo, la selección esta en la última columna, con la siguiente definición:

<p:column id="seleccionColumn" headerText="#{messages['tabla.gepeto.aPago']}" width="5%" selectionMode="multiple">
    <input type="hidden" name="disableSelect" id="disableSelect" value="#{not servicioPendientePagoBean.activarCombo(lista)}" /> 		    
</p:column>

En la definición de la columna, especificamos las siguientes propiedades:

  • El atributo id que tiene como valor obligatorio seleccionColumn, ya que se utiliza para ocultar el checkbox de selección de todos los elementos.
  • El atributo selectionMode que indica el tipo de selección, en este caso múltiple.
  • El elemento HTML input nos permite saber si la fila es seleccionable o no. En su campo value se especifica la expresión EL que obtiene dicho valor, tiene el mismo funcionamiento que la propiedad disabled de un componente JSF. Los atributos id y name de elemento input tienen que tener el valor obligatorio disableSelect, ya que se utiliza para obtener dicho valor y realizar la configuración de selección de filas.

En el componente <p:dataTable> tenemos definidas dos peticiones Ajax:

	<p:ajax event="page" oncomplete="configuraSeleccionMultiple('listaTable');"/>
	<p:ajax event="rowUnselectCheckbox" listener="#{servicioPendientePagoBean.deselecionarFila}" global="false"/>

donde:

  • page: evento que se ejecuta cuando se utiliza la paginación, y permite enviar las filas seleccionadas al bean de respaldo y almacenarlas en la lista listaServicioPendientePago mediante la llamada al método setListaServicioPendientePago. También volvemos a realizar una llamada a la función Javascript configuraSeleccionMultiple pasandole el id del componente <p:dataTable>.
  • rowUnselectCheckbox: evento que se ejecuta cuando se desmarca alguna fila, con lo que eliminamos dicha fila de la lista listaServicioPendientePago mediante la llamada al método deselecionarFila.

El resto del trabajo lo realiza el Javascript inicial.

El código Java tenemos

package es.um.atica.gepeto.backbeans;
 
...
 
@Name( ServicioPendientePagoBean.NAME )
@Scope( ScopeType.CONVERSATION )
public class ServicioPendientePagoBean extends FundeWebManagerBean {
 
    ...
 
    private List<ServicioPendientePago> listaServicioPendientePago = new ArrayList<ServicioPendientePago>();
 
    public List<ServicioPendientePago> getListaServicioPendientePago() {
        return listaServicioPendientePago;
    }
 
    public void setListaServicioPendientePago( List<ServicioPendientePago> listaServicioPendientePago ) {
        for (ServicioPendientePago servicioPendientePago : listaServicioPendientePago) {
            if (! this.listaServicioPendientePago.contains( servicioPendientePago )) {
                this.listaServicioPendientePago.add( servicioPendientePago );
            }
        }
    }
 
    public void deselecionarFila(UnselectEvent event) {
        this.listaServicioPendientePago.remove( event.getObject() );
    }
 
 
    public boolean activarCombo(ServicioPendientePago servicioPendientePago) {
         // Logica para determinar si la fila es seleccionable o no
         ...
    }
 
    ...
 
}

descripción de los métodos:

  • setListaServicioPendientePago: se utiliza para almacenar las selecciones en la lista listaServicioPendientePago. Si la lista ya contiene un elemento seleccionado, se omite.
  • deselecionarFila: se utiliza cuando se deselecciona alguna fila de la tabla. Se obtiene el objeto ServicioPendientePago del evento que tiene como parámetro y se elimina de la lista.
  • activarCombo: se utiliza para indicar si una fila esta habilitada para ser seleccionado.

JUAN MIGUEL BERNAL GONZALEZ 2016/07/15 14:45

  • fdw2.0/fundeweb2.0/gt/tabla_seleccionable.txt
  • Última modificación: 07/11/2017 10:46
  • (editor externo)