Libro JEE7 Capítulo 4. DataTable
- Para el manejo de tablas usaremos el componente <p:datatable>
- Utilizaremos el CDI Beans EstatusDataController.java , que crearemos para el manejo de la lista de estatus que serán desplegados mediante el componente datatable.
- Usaremos Método @PostConstructor
- FILTRAR Y ORDENAR REGISTROS
- DATATABLE CON FORMULARIO DE INSERCIÓN
- Datatable con Selección, Edición y Eliminación de Registros
Para el manejo de tablas usaremos el componente <p:datatable>
Utilizaremos el CDI Beans EstatusDataController.java , que crearemos para el manejo de la lista de estatus que serán desplegados mediante el componente datatable.
Usaremos Método @PostConstructor
Se utiliza para invocar métodos al inicio, lo podemos usar para invocar mediante parámetros de un CDI Beans o de Session.
Pasos:
- Creamos un List<Estatus>
List<Estatus> estatusList;
- en el constructor inicializamos el estatusList.
public EstatusDataController() {
estatusList = new ArrayList<>();
}
- Ajustar método getEstatusList()
Cambiamos el método getEstatusList()
|
por
|
public List<Estatus> getEstatusList() {
return estatusFacade.getEstatusList();
}
|
public List<Estatus> getEstatusList() {
return estatusList;
}
|
- crear los métodos set para estatusList, podemos utilizar el asistente clic derecho Insert code -->Getter and Setter… seleccionar estatusList
public void setEstatusList(List<Estatus> estatusList) {
this.estatusList = estatusList;
}
Creamos el método init con la anotación @PostConstruct, que sera invocado la primera vez que se carga el CDIBeans.Se usara otro metodo iniciar(), para el caso que deba ser invocado nuevamente.
@PostConstruct
public void init(){
iniciar();
}
corregimos los import
Crear el método iniciar() para cargar registros.
public void iniciar(){
estatusList = estatusFacade.getEstatusList();
}
Crear otro método iniciar con parámetro String ,este recibirá un parámetro para establecer el filtro de las entidades a mostrar en el datatable.
public void iniciar(String value){
estatusList = estatusFacade.findByEsinicial(value);
}
Editar el método delete() y agregar la invocación al método iniciar(); de manera que carge el list actualizado.
public String delete() {
try {
estatusFacade.remove(selected);
iniciar();
JSFUtil.addSuccessMessage(rf.getMensajeArb("info.delete"));
} catch (Exception e) {
JSFUtil.addErrorMessage(e.getLocalizedMessage());
}
return null;
}
Si deseamos filtrar los registros iniciales
para obtener los filtrados por el atributo esinicial=”no”
En el método init() de r, invocamos el método iniciar( con el parámetro no), para que devuelva los registros que cumplan esa condición.
@PostConstruct
public void init(){
//iniciar();
iniciar("no");
}
Solo se muestran los registros con esincial = “no”
Otra forma seria para invocar el método antes de cargar la página, en el código xhtml , en la sección metadata, indicamos el parámetro, y el viewAction.
<f:metadata>
<f:viewParam name="id" value="#{estatusDataController.estatus.idestatus}"/>
<f:viewAction action="#{estatusDataController.iniciar}"/>
</f:metadata>
FILTRAR Y ORDENAR REGISTROS
Agregamos un list del Entity Estatus
private List<Estatus> filtered;
y creamos los métodos set/get
public List<Estatus> getFiltered() {
return filtered;
}
public void setFiltered(List<Estatus> filtered) {
this.filtered = filtered;
}
En el componente dataTable agregar filteredValue="#{estatusDataController.filtered}"
<p:dataTable id="datatable" paginator="true" rows="7" value="#{estatusDataController.estatusList}"
var="item"
rowKey="#{item.idestatus}"
selectionMode="single"
selection="#{estatusDataController.selected}"
filteredValue="#{estatusDataController.filtered}"
>
En las columnas colocamos para filtrar por cada atributo filterBy="#{item.idestatus}" y para ordenar sortBy="#{item.idestatus}"
<p:column style="width:5%" filterBy="#{item.idestatus}" sortBy="#{item.idestatus}">
<f:facet name="header">
<h:outputText value="#{msg.idestatus}"/>
</f:facet>
<h:outputText value="#{item.idestatus}"/>
</p:column>
en el browser, se muestra el componente para filtrar y ordenar
Agregaremos un dialogo con la propiedad es visible=”true”
<p:dialog visible="true" header="#{app['form.estatuslist']}" closable="false"
showEffect="clip" hideEffect="fade" widgetVar="estatuslistDialog">
DATATABLE CON FORMULARIO DE INSERCIÓN
PrimeFaces ofrece el componente <p:datatable> que permite generar una tabla en la página, con opciones como búsquedas, filtros, selección de filas.
Usaremos Named Queries, para obtener la lista de Entitys que cumplan los criterios deseados, de manera que podamos realizar operaciones de edición o eliminación sobre los mismos.
Si observamos en el entity “Estatus”, podemos ver las definiciones y Bean Validation como mostramos a continuación.
Formulario de estatusinsert .xthml
Ubicarse en el formulario estatusinsert.xhtml antes de </h:form> y
dar clic derecho y seleccionar insert code
seleccionar JSF Data Table From Entity
En el cuadro de diálogo que se presenta seleccionamos Estatus como Entity y como ManagedBean Property estatusDataController estatusList
El ide genera el siguiente código
<h:form>
<h1><h:outputText value="List"/></h1>
<h:dataTable value="#{estatusDataController.estatusList}" var="item">
<h:column>
<f:facet name="header">
<h:outputText value="Idestatus"/>
</f:facet>
<h:outputText value="#{item.idestatus}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Estatus"/>
</f:facet>
<h:outputText value="#{item.estatus}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Esinicial"/>
</f:facet>
<h:outputText value="#{item.esinicial}"/>
</h:column>
</h:dataTable>
</h:form>
Quitamos el componente <h:form> y </h:form> del datatable de manera que únicamente exista el form principal. Como se muestra a continuación en el browser, tendremos los registros de estatus
Cambiaremos las etiquetas <h:datatable> por <p:datatable> y <h:column> por <p:column> para usar los componentes primefaces y se usarán las etiquetas de los archivos de propiedades en los header de cada columna.
Esto permitirá que al cambiar el idioma el encabezado de cada columna cambie automáticamente.
<f:facet name="header">
<h:outputText value="Idestatus"/>
</f:facet>
por
<f:facet name="header">
<h:outputText value="#{msg.idestatus}"/>
</f:facet>
Colocamos el id=”datatable”, paginación de la tabla y el número de filas
<p:dataTable id="datatable" paginator="true" rows="7" value="#{estatusDataController.estatusList}" var="item">
Despues de los cambios quedaria de la siguiente manera.
Para actualizar el datatable al agregar un registro, en el commandButton que utilizamos para guardar , agregamos al update el componente datatable, de esta manera se mostrará en el datatable los cambios sin renderizar el formulario completo.
<p:commandButton value="#{app['boton.save']}" update="panel,growl,datatable" action="#{estatusDataController.save()}"/>
Al crear un nuevo estatus este automáticamente actualiza la tabla
Removemos el código que utilizamos del datatable del formulario estatusinsert.xhtml, ya que crearemos una página xhtml que se encargara de mostrar , editar y eliminar los registros.
Y eliminamos del <p:commandButton en el método update la actualización datatable.
Datatable con Selección, Edición y Eliminación de Registros
Aquí mostraremos como crear una página que permite mostrar los registros, realizar búsquedas e invocar un diálogo para realizar la edición de los registros.
Creamos una página nueva llamada estatuslist.xhtml en el directorio /page/estatus
Ahora creamos un Facelets Template Client
- Desde menú File, seleccione New
- en Categories, seleccione Java Server Faces
- en File Types, seleccione Facelets Template Client
- En File Name: estatuslist
- Folder colocamos /page/estatus/
- Template seleccionamos template.xhtml
Se genera el código de la página y colocamos en comentario top,bottom, left <!-- - -> para que este tome el que este utilice el que esta en el template, y en center escribimos
Editamos estatuslist.xhtml , nos ubicamos en la sección center y
dar clic derecho y seleccionar insert code , seleccionar JSF Data Table From Entity
Seleccionar Entity Estatus y el CDI Property estatusDataController propiedad estatusList
Colocar el id para el form
<h:form id="form">
En el código generado, nos ubicamos en <h:datatable> y <h:column> y los reemplazamos por <p:datatable> y <p:column> para utilizar los componentes primefaces.
Modificamos el componente dataTable original, indicando el número de filas(rows), value indicamos el list de objetos, var define la variable para indicar los elementos, selectionMode define el modo de selección y selection asocia al entity la fila seleccionada.
<p:dataTable id="datatable" paginator="true"
rows="7" value="#{estatusDataController.estatusList}" var="item"
rowKey="#{item.idestatus}"
selectionMode="single"
selection="#{estatusDataController.selected}"
>
Ejecutamos el proyecto , podemos ver los registros en el datatable
Agregamos el evento ajax oncomplete() para mostrar un diálogo con la fila seleccionada , y actualizaremos mediante update el growl y el panel que contendrá el entity seleccionado de la fila.
Para mostrar el dialogo usamos oncomplete="PF('editwidgetVar').show()"/>.
Si deseamos ocultarlo usamos oncomplete="PF('editwidgetVar').hide()"/>
Codigo del datatable
<h1><h:outputText value="#{app['form.estatuslist']}" /></h1>
<p:dataTable id="datatable" paginator="true"
rows="7" value="#{estatusDataController.estatusList}" var="item"
rowKey="#{item.idestatus}"
selectionMode="single"
selection="#{estatusDataController.selected}"
>
<p:ajax event="rowSelect"
oncomplete="PF('editwidgetVar').show();"
update=":form:growl,:form:displayEdit" />
Nos ubicamos debajo de </p:dataTable>, colocamos el componente dialog y un panelGrid. La propiedad widgetVar se usará para asignar un nombre al componente que será localizado mediante PrimefacesFramework PF().
<p:dialog id="editDialog" header="#{app['dialog.edit']}" widgetVar="editwidgetVar"
resizable="false" height="235" width="550" showEffect="clip" hideEffect="fold">
<h:panelGrid id="displayEdit" columns="2" title="#{app['dialog.edit']}">
</h:panelGrid>
</p:dialog>
Ubicarse dentro del panelgrid <h:panelGrid id="displayEdit" y dar clic derecho Insert Code→ seleccionar JSF Form From Entity
Ahora seleccionar el Entity Estatus y el Managed Bean Property selecionar selected
se genera el código, y debemos eliminar las etiquetas <h:form> y </h:form> ya que tenemos un formulario principal.
Eliminar <h1><h:outputText value="Create/Edit"/></h1>
Y colocamos las etiquetas de los properties, el title y requiredMessage para los componentes utilizados.
Cambiamos el <h:inputText id="esinicial" … />, por el selectOneMenu similar al que usamos en el formulario insert.
<p:selectOneMenu id="esinicial" value="#{estatusDataController.selected.esinicial}" required="true" requiredMessage="#{msg.esinicial} #{app['info.notnull']}">
<f:selectItem itemLabel="#{app['boton.yes']}" itemValue="si" />
<f:selectItem itemLabel="#{app['boton.no']}" itemValue="no" />
</p:selectOneMenu>
Creamos la sección<f:facet name="footer"> del panelGrid y colocamos los botones para editar, eliminar,cerrar. El botón eliminar mostrará un diálogo solicitando la confirmación de si eliminamos o no el registro.
<f:facet name="footer">
<p:commandButton id="editButton" value="#{app['boton.update']}"
update=":form:growl,:form:datatable,:form:displayEdit"
actionListener="#{estatusDataController.edit()}"
oncomplete="PF('editwidgetVar').hide()"/>
<p:commandButton id="deleteButton" value="#{app['boton.delete']}" title="#{app['boton.delete']}" onclick="PF('confirmationwidgetVar').show();" type="button" icon="ui-icon-trash" />
<p:commandButton id="declineButton" value="#{app['boton.cerrar']}" onclick="PF('editwidgetVar').hide();" type="button" />
</f:facet>
Agregar antes del </h:form> el growl y el componente para mensajes
<p:growl id="growl"/>
<p:messages autoUpdate="true"/>
En el browser al dar clic en la fila se muestra el registro con las opciones de editar/eliminar
Al presionar el boton eliminar se muestra el diálogo para confirmar
Para ajustar el tamaño de las columnas podemos hacerlo de dos maneras
<p:column style="width:20%">
o
<p:column style="width:5%; text-align:center;"> si lo deseamos centrado.
Código completo estatuslist.xhtml
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:p="http://primefaces.org/ui">
<body>
<ui:composition template="./../../template.xhtml">
<!--
<ui:define name="top">
top
</ui:define>
<ui:define name="bottom">
bottom
</ui:define>
<ui:define name="left">
left
</ui:define>
-->
<ui:define name="center">
<f:view>
<h:form id="form" >
<p:dialog visible="true" header="#{app['form.estatuslist']}" closable="false"
showEffect="clip" hideEffect="fade" widgetVar="estatuslistDialog">
<h1><h:outputText value="List"/></h1>
<p:dataTable id="datatable" paginator="true"
rows="7" value="#{estatusDataController.estatusList}" var="item"
rowKey="#{item.idestatus}"
selectionMode="single"
selection="#{estatusDataController.selected}"
filteredValue="#{estatusDataController.filtered}"
>
<p:ajax event="rowSelect"
oncomplete="PF('editwidgetVar').show();"
update=":form:growl,:form:displayEdit"/>
<p:column style="width:20%" filterBy="#{item.idestatus}" sortBy="#{item.idestatus}">
<f:facet name="header">
<h:outputText value="#{msg.idestatus}"/>
</f:facet>
<h:outputText value="#{item.idestatus}"/>
</p:column>
<p:column filterBy="#{item.estatus}" sortBy="#{item.estatus}">
<f:facet name="header">
<h:outputText value="#{msg.estatus}"/>
</f:facet>
<h:outputText value="#{item.estatus}"/>
</p:column>
<p:column filterBy="#{item.esinicial}" sortBy="#{item.esinicial}">
<f:facet name="header">
<h:outputText value="#{msg.esinicial}"/>
</f:facet>
<h:outputText value="#{item.esinicial}"/>
</p:column>
</p:dataTable>
</p:dialog>
<p:dialog id="editDialog" header="#{app['dialog.edit']}" widgetVar="editwidgetVar"
resizable="false" height="235" width="550" showEffect="clip" hideEffect="fold">
<h:panelGrid id="displayEdit" columns="2" title="#{app['dialog.edit']}">
<h1><h:outputText value="Create/Edit"/></h1>
<h:panelGrid columns="2">
<h:outputLabel value="Idestatus:" for="idestatus" />
<h:inputText id="idestatus" value="#{estatusDataController.selected.idestatus}" title="Idestatus" required="true" requiredMessage="The Idestatus field is required."/>
<h:outputLabel value="Estatus:" for="estatus" />
<h:inputText id="estatus" value="#{estatusDataController.selected.estatus}" title="Estatus" required="true" requiredMessage="The Estatus field is required."/>
<h:outputLabel value="Esinicial:" for="esinicial" />
<p:selectOneMenu id="esinicial"
value="#{estatusDataController.selected.esinicial}" required="true"
requiredMessage="#{msg.esinicial} #{app['info.notnull']}">
<f:selectItem itemLabel="#{app['boton.yes']}" itemValue="si" />
<f:selectItem itemLabel="#{app['boton.no']}" itemValue="no" />
</p:selectOneMenu>
<f:facet name="footer">
<p:commandButton id="editButton" value="#{app['boton.update']}"
update=":form:growl,:form:datatable,:form:displayEdit"
actionListener="#{estatusDataController.edit()}"
oncomplete="PF('editwidgetVar').hide()"/>
<p:commandButton id="deleteButton" value="#{app['boton.delete']}"
title="#{app['boton.delete']}" onclick="PF('confirmationwidgetVar').show();" type="button"
icon="uiicontrash" />
<p:commandButton id="declineButton" value="#{app['boton.cerrar']}"
onclick="PF('editwidgetVar').hide();" type="button" />
</f:facet>
</h:panelGrid>
</h:panelGrid>
</p:dialog>
<p:dialog id="confirmDialog" modal="false" header="#{app['boton.delete']}"
widgetVar="confirmationwidgetVar">
<p:commandButton id="removeButton" value="#{app['boton.yes']}"
update=":form:displayEdit, :form:growl, :form:datatable"
oncomplete="PF('confirmationwidgetVar').hide();,
PF('editwidgetVar').hide();"
actionListener="#{estatusDataController.delete()}" />
<p:commandButton id="cancelButton" value="#{app['boton.no']}"
onclick="PF('confirmationwidgetVar').hide()" type="button" />
</p:dialog>
<p:growl id="growl"/>
<p:messages autoUpdate="true"/>
</h:form>
</f:view>
</ui:define>
</ui:composition>
</body>
</html>
Crear un CDI Beans para gestionar las list de entity para mostrar en las páginas
- Desde menú File, seleccione New
- en Categories, seleccione Java Server Faces
- en File Types, seleccione JSF ManagedBeans
- Class Name: EstatusDataController
- Package com.avbravo.scrumweb.controller
- Scope: View
Cambiar
|
Reemplazar
|
@ManagedBeans
|
@Named
|
import javax.faces.bean.ManagedBean;
|
import javax.inject.Named;
|
import javax.faces.bean.ViewScoped;
|
import javax.faces.view.ViewScoped;
|
Implementamos serializable,
inyectamos mediante @Inject EstatusFacade, ResourceFiles.
Agregamos un objeto de tipo estatus que se utilizará para hacer referencia al entity seleccionado del datatable.
Estatus selected = new Estatus();
generamos los métodos get/set, para ello hacemos clic derecho Insert Code y seleccionar Getter and Setter…
Seleccionar selected: Estatus, tal como aparece en la imagen
el IDE genera los métodos
public Estatus getSelected() {
return selected;
}
public void setSelected(Estatus selected) {
this.selected = selected;
}
Además se creará el método edit() para actualizar registros y delete() para eliminarlo.
Crear método getEstatusList() para que devuelva un list de estatus
public List<Estatus> getEstatusList() {
return estatusFacade.getEstatusList();
}
Código de EstatusDataController.java
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.avbravo.scrumweb.controller;
import com.avbravo.scrumweb.Estatus;
import com.avbravo.scrumweb.ejb.EstatusFacade;
import com.avbravo.scrumweb.generales.JSFUtil;
import com.avbravo.scrumweb.generales.ResourcesFiles;
import java.io.Serializable;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.view.ViewScoped;
import javax.inject.Inject;
import javax.inject.Named;
/**
*
* @author avbravo
*/
@Named
@ViewScoped
public class EstatusDataController implements Serializable {
private static final long serialVersionUID = 1L;
@Inject
EstatusFacade estatusFacade;
@Inject
ResourcesFiles rf;
Estatus selected = new Estatus();
List<Estatus> filtered;
List<Estatus> estatusList;
public List<Estatus> getFiltered() {
return filtered;
}
public void setFiltered(List<Estatus> filtered) {
this.filtered = filtered;
}
public Estatus getSelected() {
return selected;
}
public void setSelected(Estatus selected) {
this.selected = selected;
}
/**
* Creates a new instance of EstatusDataController
*/
public EstatusDataController() {
}
public void setEstatusList(List<Estatus> estatusList) {
this.estatusList = estatusList;
}
public List<Estatus> getEstatusList() {
// return estatusFacade.getEstatusList();
return estatusList;
}
@PostConstruct
public void init() {
iniciar();
}
public void iniciar() {
estatusList = estatusFacade.getEstatusList();
}
public void iniciar(String value) {
estatusList = estatusFacade.findByEsinicial(value);
}
public String edit() {
try {
estatusFacade.edit(selected);
JSFUtil.addSuccessMessage(rf.getMensajeArb("info.update"));
} catch (Exception e) {
JSFUtil.addErrorMessage(e.getLocalizedMessage());
}
return null;
}
public String delete() {
try {
estatusFacade.remove(selected);
JSFUtil.addSuccessMessage(rf.getMensajeArb("info.delete"));
iniciar();
} catch (Exception e) {
JSFUtil.addErrorMessage(e.getLocalizedMessage());
}
return null;
}
}
Comments